├── .codeclimate.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src └── Cnab │ ├── Banco.php │ ├── CodigoCarteira.php │ ├── Especie.php │ ├── Factory.php │ ├── Format │ ├── Field.php │ ├── Identifier.php │ ├── Linha.php │ ├── Picture.php │ └── YamlLoad.php │ ├── Instrucao.php │ ├── Remessa │ ├── Cnab240 │ │ ├── Arquivo.php │ │ ├── Detalhe.php │ │ ├── HeaderArquivo.php │ │ ├── HeaderLote.php │ │ ├── SegmentoP.php │ │ ├── SegmentoQ.php │ │ ├── SegmentoR.php │ │ ├── TrailerArquivo.php │ │ └── TrailerLote.php │ ├── Cnab400 │ │ ├── Arquivo.php │ │ ├── Detalhe.php │ │ ├── DetalheMulta.php │ │ ├── Header.php │ │ └── Trailer.php │ └── IArquivo.php │ └── Retorno │ ├── Cnab240 │ ├── Arquivo.php │ ├── Detalhe.php │ ├── HeaderArquivo.php │ ├── HeaderLote.php │ ├── Lote.php │ ├── SegmentoT.php │ ├── SegmentoU.php │ ├── SegmentoW.php │ ├── TrailerArquivo.php │ └── TrailerLote.php │ ├── Cnab400 │ ├── Arquivo.php │ ├── Detalhe.php │ ├── Header.php │ └── Trailer.php │ ├── CodigoOcorrencia.php │ ├── IArquivo.php │ ├── IDetalhe.php │ └── Linha.php └── tests ├── Cnab ├── BancoTest.php ├── Format │ ├── LinhaTest.php │ ├── PictureTest.php │ └── YamlLoadTest.php ├── Remessa │ ├── Cnab240 │ │ ├── BancoDoBrasilTest.php │ │ └── CaixaTest.php │ └── Cnab400 │ │ └── ArquivoTest.php └── Retorno │ ├── Cnab240 │ └── ArquivoTest.php │ ├── Cnab400 │ └── ArquivoTest.php │ └── CodigoOcorrenciaTest.php ├── bootstrap.php ├── exemplo_gerar_teste.php └── fixtures ├── cnab240 ├── retorno_bb.ret ├── retorno_cnab240_caixa.ret └── retorno_santander.ret └── cnab400 ├── retorno-cb030400-bradesco.ret ├── retorno-cnab400-bb.ret └── retorno-cnab400-itau.ret /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | languages: 2 | Ruby: false 3 | JavaScript: false 4 | PHP: true 5 | exclude_paths: 6 | - "vendor/*" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Vim 2 | *.swp 3 | *.swo 4 | bin 5 | vendor 6 | composer.phar 7 | phpunit.xml 8 | composer.lock 9 | nbproject -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | script: phpunit --verbose --coverage-text 3 | 4 | php: 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | - 7.0 9 | 10 | before_script: 11 | - "composer install -v" 12 | 13 | after_script: 14 | - "phpunit --testdox" 15 | 16 | after_script: 17 | - "phpunit --testdox" 18 | - "phpunit --coverage-clover build/logs/clover.xml" 19 | - "bin/test-reporter --stdout > codeclimate.json; curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports" 20 | 21 | addons: 22 | code_climate: 23 | repo_token: 62106545f2b8d419b073155b0af4bd0b9b3233707007fd8950f453c103ad834d 24 | 25 | notifications: 26 | webhooks: 27 | urls: 28 | - https://webhooks.gitter.im/e/4fbdd69a8426f4b5ae9a 29 | on_success: change # options: [always|never|change] default: always 30 | on_failure: always # options: [always|never|change] default: always 31 | on_start: never # options: [always|never|change] default: always 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Anderson Danilo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CnabPHP 2 | ======= 3 | 4 | [![Join the chat at https://gitter.im/andersondanilo/CnabPHP](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/andersondanilo/CnabPHP?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | [![Build Status](https://secure.travis-ci.org/andersondanilo/CnabPHP.png?branch=master)](http://travis-ci.org/andersondanilo/CnabPHP) 7 | [![Latest Stable Version](https://poser.pugx.org/andersondanilo/cnab_php/v/stable.svg)](https://packagist.org/packages/andersondanilo/cnab_php) 8 | [![Latest Unstable Version](https://poser.pugx.org/andersondanilo/cnab_php/v/unstable.svg)](https://packagist.org/packages/andersondanilo/cnab_php) 9 | [![Code Climate](https://codeclimate.com/github/andersondanilo/CnabPHP/badges/gpa.svg)](https://codeclimate.com/github/andersondanilo/CnabPHP) 10 | [![Test Coverage](https://codeclimate.com/github/andersondanilo/CnabPHP/badges/coverage.svg)](https://codeclimate.com/github/andersondanilo/CnabPHP/coverage) 11 | 12 | 13 | Projeto para criar arquivos de remessas e processar arquivos de retorno no formato CNAB, utilizado nos bancos geralmente para boleto bancário. 14 | 15 | 16 | ## Funcionalidades 17 | 18 | * Leitura e geração de arquivos de retorno e remessa nos formatos CNAB 240 e 400 19 | 20 | | Banco | Versão da Remessa | Versão do Retorno | 21 | |-----------------|--------------------|--------------------| 22 | | Banco do Brasil | 240 (Beta) | 240 e 400 | 23 | | Bradesco | | 240 | 24 | | Caixa | 240 | 240 e 400 | 25 | | Itaú | 400 | 400 | 26 | | Santander | | 240 | 27 | 28 | ## Instalação 29 | ### Composer 30 | Se você já conhece o **Composer**, adicione a dependência abaixo à diretiva *"require"* no seu **composer.json**: 31 | ``` 32 | "andersondanilo/cnab_php": "1.3.*" 33 | ``` 34 | 35 | ## Como Usar 36 | ### Lendo um arquivo de Retorno 37 | ```php 38 | $cnabFactory = new Cnab\Factory(); 39 | $arquivo = $cnabFactory->createRetorno('AQUI VAI O CAMINHO DO ARQUIVO DE RETORNO, EX: RET1010.RET'); 40 | $detalhes = $arquivo->listDetalhes(); 41 | foreach($detalhes as $detalhe) { 42 | if($detalhe->getValorRecebido() > 0) { 43 | $nossoNumero = $detalhe->getNossoNumero(); 44 | $valorRecebido = $detalhe->getValorRecebido(); 45 | $dataPagamento = $detalhe->getDataOcorrencia(); 46 | $carteira = $detalhe->getCarteira(); 47 | // você já tem as informações, pode dar baixa no boleto aqui 48 | } 49 | } 50 | ``` 51 | ### Criando um arquivo de remessa 52 | 53 | Consulte na wiki: https://github.com/andersondanilo/CnabPHP/wiki/Criando-um-arquivo-de-remessa 54 | 55 | ## Como Contribuir 56 | Você pode contribuir com testes (unitários ou manuais), ou adaptando o formato para outro banco através do projeto cnab_yaml (https://github.com/andersondanilo/cnab_yaml) (que é utilizado pelo cnab_php). [Leia a wiki](https://github.com/andersondanilo/CnabPHP/wiki) 57 | 58 | O projeto está usando o Waffle para gerenciar o status da impleentação de novas remessas e retornos: 59 | 60 | [![Stories in Ready](https://badge.waffle.io/andersondanilo/CnabPHP.png?label=ready&title=Ready)](http://waffle.io/andersondanilo/CnabPHP) 61 | 62 | 63 | ## Licença 64 | Este projeto esta sobre a licença MIT 65 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "andersondanilo/cnab_php", 3 | "type": "library", 4 | "description": "Projeto para criar arquivos de remessas e processar arquivos de retorno no formato CNAB", 5 | "keywords": ["boleto", "remessa", "retorno"], 6 | "licence": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Anderson Danilo", 10 | "email": "andersondanilo.souza@gmail.com" 11 | }, 12 | { 13 | "name": "Hermenegildo Marin Junior", 14 | "email": "hmarinjr@gmail.com" 15 | } 16 | ], 17 | "require-dev": { 18 | "phpunit/phpunit": "3.7.*", 19 | "phpunit/php-code-coverage": "1.2.*", 20 | "codeclimate/php-test-reporter": "dev-master" 21 | }, 22 | "require": { 23 | "andersondanilo/cnab_yaml": "~1.3", 24 | "php": ">=5.4.0", 25 | "mustangostang/spyc": "0.5.*" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "Cnab\\": "src/Cnab" 30 | } 31 | }, 32 | "config": { 33 | "bin-dir": "bin" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | tests 11 | 12 | 13 | 14 | 15 | src 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Cnab/Banco.php: -------------------------------------------------------------------------------- 1 | self::BANCO_DO_BRASIL, 18 | 'nome_do_banco' => 'BANCO DO BRASIL S.A.', 19 | ); 20 | } elseif ($codigo == self::ITAU) { 21 | return array( 22 | 'codigo_do_banco' => self::ITAU, 23 | 'nome_do_banco' => 'BANCO ITAU SA', 24 | ); 25 | } elseif ($codigo == self::CEF) { 26 | return array( 27 | 'codigo_do_banco' => self::CEF, 28 | 'nome_do_banco' => 'CAIXA ECONOMICA FEDERAL', 29 | ); 30 | } elseif ($codigo == self::SANTANDER) { 31 | return array( 32 | 'codigo_do_banco' => self::SANTANDER, 33 | 'nome_do_banco' => 'BANCO SANTANDER (BRASIL) S/A', 34 | ); 35 | } elseif ($codigo == self::BRADESCO) { 36 | return array( 37 | 'codigo_do_banco' => self::BRADESCO, 38 | 'nome_do_banco' => 'BRADESCO', 39 | ); 40 | } else { 41 | return false; 42 | } 43 | } 44 | 45 | public static function existBanco($codigo_banco) 46 | { 47 | $banco = self::getBanco($codigo_banco); 48 | 49 | return $banco ? true : false; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Cnab/CodigoCarteira.php: -------------------------------------------------------------------------------- 1 | identifyFile($filename); 68 | 69 | if (!$format) { 70 | throw new \Exception('Formato do arquivo não identificado'); 71 | } 72 | 73 | if ($format['tipo'] != 'retorno') { 74 | throw new \Exception('Este não é um arquivo de retorno'); 75 | } 76 | 77 | if (!$format['banco']) { 78 | throw new \Exception('Banco não suportado'); 79 | } 80 | 81 | if (!\Cnab\Banco::existBanco($format['banco'])) { 82 | throw new \Exception('Banco não suportado'); 83 | } 84 | 85 | // por enquanto só suporta o Cnab400 86 | 87 | if ($format['bytes'] == 400) { 88 | return new Retorno\Cnab400\Arquivo($format['banco'], $filename, $format['layout_versao']); 89 | } elseif ($format['bytes'] == 240) { 90 | return new Retorno\Cnab240\Arquivo($format['banco'], $filename, $format['layout_versao']); 91 | } else { 92 | throw new \Exception('Formato não suportado'); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Cnab/Format/Field.php: -------------------------------------------------------------------------------- 1 | options = $options; 25 | $this->nome = $nome; 26 | $this->cnabLinha = $linha; 27 | $this->format = $format; 28 | $this->pos_start = $pos_start; 29 | $this->pos_end = $pos_end; 30 | $this->length = ($pos_end + 1) - $pos_start; 31 | 32 | $p_length = Picture::getLength($this->format); 33 | if ($p_length > $this->length) { 34 | throw new \Exception("Picture length of '$this->nome' need more positions than $pos_start : $pos_end"); 35 | } elseif ($p_length < $this->length) { 36 | throw new \Exception("Picture length of '$this->nome' need less positions than $pos_start : $pos_end"); 37 | } 38 | } 39 | 40 | public function set($valor) 41 | { 42 | if ($valor === false || is_null($valor)) { 43 | throw new \Exception("'$this->nome' dont be false or null"); 44 | } 45 | 46 | $this->valor_decoded = $valor; 47 | 48 | try { 49 | $this->valor_encoded = Picture::encode($valor, $this->format, $this->options); 50 | } catch (\Exception $e) { 51 | trigger_error("Error in field '$this->nome': ".$e->getMessage(), E_USER_NOTICE); 52 | throw $e; // para exibir o backtrace 53 | } 54 | 55 | $len = strlen($this->valor_encoded); 56 | if ($len != $this->length) { 57 | throw new \Exception("'$this->nome' have length '$len', but field need length $this->length"); 58 | } 59 | } 60 | 61 | public function getValue() 62 | { 63 | return $this->valor_decoded; 64 | } 65 | 66 | public function getName() 67 | { 68 | return $this->nome; 69 | } 70 | 71 | public function getEncoded() 72 | { 73 | if (is_null($this->valor_encoded)) { 74 | throw new \Exception("'$this->nome' dont be null, need to set any value"); 75 | } 76 | 77 | return $this->valor_encoded; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Cnab/Format/Identifier.php: -------------------------------------------------------------------------------- 1 | $codigo_banco, 81 | 'tipo' => $tipo, 82 | 'bytes' => $bytes, 83 | 'layout_versao' => $layout_versao, 84 | ); 85 | 86 | return $result; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Cnab/Format/Linha.php: -------------------------------------------------------------------------------- 1 | fields)) { 13 | $this->fields[$key]->set($valor); 14 | } else { 15 | throw new \InvalidArgumentException("field '$key' dont exists"); 16 | } 17 | } 18 | 19 | public function __get($key) 20 | { 21 | if (\array_key_exists($key, $this->fields)) { 22 | return $this->fields[$key]->getValue(); 23 | } else { 24 | throw new \InvalidArgumentException("field '$key' dont exists"); 25 | } 26 | } 27 | 28 | public static function cmpSortFields(Field $field1, Field $field2) 29 | { 30 | return $field1->pos_start > $field2->pos_start ? 1 : -1; 31 | } 32 | 33 | public function addField($nome, $pos_start, $pos_end, $format, $default, $options) 34 | { 35 | foreach ($this->fields as $key => $field) { 36 | $current_pos_start = $field->pos_start; 37 | $current_pos_end = $field->pos_end; 38 | 39 | if (($pos_start >= $current_pos_start && $pos_start <= $current_pos_end) || 40 | ($pos_end <= $current_pos_end && $pos_end >= $current_pos_start) || 41 | ($current_pos_start >= $pos_start && $current_pos_start <= $pos_end) || 42 | ($current_pos_end <= $pos_end && $current_pos_end >= $pos_start)) { 43 | unset($this->fields[$key]); 44 | } 45 | } 46 | 47 | $this->fields[$nome] = new Field($this, $nome, $format, $pos_start, $pos_end, $options); 48 | if ($default !== false) { 49 | $this->fields[$nome]->set($default); 50 | } 51 | } 52 | 53 | public function loadFromString($text) 54 | { 55 | foreach ($this->fields as $field) { 56 | $field->set(Picture::decode(\substr($text, $field->pos_start - 1, $field->length), $field->format, $field->options)); 57 | } 58 | } 59 | 60 | public function getEncoded() 61 | { 62 | if ($this->validate()) { 63 | $max_pos_end = 0; 64 | $dados = ''; 65 | $fields = $this->fields; 66 | usort($fields, 'self::cmpSortFields'); 67 | $lastField = null; 68 | foreach ($fields as $field) { 69 | if ($lastField && $field->pos_start != $lastField->pos_end + 1) { 70 | throw new \Exception("gap between {$lastField->nome} and {$field->nome}"); 71 | } 72 | $dados .= $field->getEncoded(); 73 | if ($field->pos_end > $max_pos_end) { 74 | $max_pos_end = $field->pos_end; 75 | } 76 | $lastField = $field; 77 | } 78 | 79 | if (strlen($dados) != $max_pos_end) { 80 | throw new \Exception('line length is '.\strlen($dados)." and max pos_end is $max_pos_end"); 81 | } 82 | 83 | return $dados; 84 | } else { 85 | return false; 86 | } 87 | } 88 | 89 | public function getFields() 90 | { 91 | return $this->fields; 92 | } 93 | 94 | public function validate() 95 | { 96 | foreach ($this->fields as $fieldNome => $field) { 97 | if ($field->getValue() === null || $field->getValue() === false) { 98 | $this->last_error = "$fieldNome dont be null or false"; 99 | 100 | return false; 101 | } 102 | } 103 | 104 | return true; 105 | } 106 | 107 | public function existField($name) 108 | { 109 | $exist = \array_key_exists($name, $this->fields); 110 | 111 | return $exist ? true : false; 112 | } 113 | 114 | public function dump() 115 | { 116 | $dump = ''; 117 | $dump .= PHP_EOL; 118 | $dump .= '============= Dump =============='; 119 | $dump .= PHP_EOL; 120 | foreach ($this->fields as $fieldNome => $field) { 121 | $dump .= $fieldNome.': '; 122 | $dump .= $field->getValue(); 123 | $dump .= PHP_EOL; 124 | } 125 | 126 | return $dump; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Cnab/Format/Picture.php: -------------------------------------------------------------------------------- 1 | X|9)\((?P[0-9]+)\)(?P(V9)?)\(?(?P([0-9]+)?)\)?/'; 8 | 9 | public static function validarFormato($format) 10 | { 11 | if (\preg_match(self::REGEX_VALID_FORMAT, $format)) { 12 | return true; 13 | } else { 14 | return false; 15 | } 16 | } 17 | 18 | public static function getLength($format) 19 | { 20 | $m = array(); 21 | if (preg_match(self::REGEX_VALID_FORMAT, $format, $m)) { 22 | return (int) $m['tamanho1'] + (int) $m['tamanho2']; 23 | } else { 24 | throw new \InvalidArgumentException("'$format' is not a valid format"); 25 | } 26 | } 27 | 28 | public static function parseNumber($value) 29 | { 30 | $value = preg_replace('/[^0-9.]/', '', $value); 31 | $value = preg_replace('/^0+/', '', $value); 32 | if ($value) { 33 | return $value; 34 | } else { 35 | return '0'; 36 | } 37 | } 38 | 39 | public static function encode($value, $format, $options) 40 | { 41 | $m = array(); 42 | if (\preg_match(self::REGEX_VALID_FORMAT, $format, $m)) { 43 | if ($m['tipo1'] == 'X' && !$m['tipo2']) { 44 | $value = \substr($value, 0, $m['tamanho1']); 45 | 46 | return \str_pad($value, (int) $m['tamanho1'], ' ', STR_PAD_RIGHT); 47 | } elseif ($m['tipo1'] == '9') { 48 | if ($value instanceof \DateTime) { 49 | if (@$options['date_format']) { 50 | $value = strftime($options['date_format'], $value->getTimestamp()); 51 | } else { 52 | if ((int) $m['tamanho1'] == 8) { 53 | $value = $value->format('dmY'); 54 | } 55 | 56 | if ((int) $m['tamanho1'] == 6) { 57 | $value = $value->format('dmy'); 58 | } 59 | } 60 | } 61 | 62 | if (!is_numeric($value)) { 63 | throw new \Exception("value '$value' dont is a number, need format $format"); 64 | } 65 | 66 | $value = self::parseNumber($value); 67 | $exp = explode('.', $value); 68 | if (!isset($exp[1])) { 69 | $exp[1] = 0; 70 | } 71 | if ($m['tipo2'] == 'V9') { 72 | $tamanho_left = (int) $m['tamanho1']; 73 | $tamanho_right = (int) $m['tamanho2']; 74 | $valor_left = \str_pad($exp[0], $tamanho_left, '0', STR_PAD_LEFT); 75 | if (strlen($exp[1]) > $tamanho_right) { 76 | $extra = strlen($exp[1]) - $tamanho_right; 77 | $extraPow = pow(10, $extra); 78 | $exp[1] = round($exp[1] / $extraPow); 79 | } 80 | $valor_right = \str_pad($exp[1], $tamanho_right, '0', STR_PAD_RIGHT); 81 | 82 | return $valor_left.$valor_right; 83 | } elseif (!$m['tipo2']) { 84 | $value = self::parseNumber($value); 85 | 86 | return \str_pad($value, (int) $m['tamanho1'], '0', STR_PAD_LEFT); 87 | } else { 88 | throw new \InvalidArgumentException("'$format' is not a valid format"); 89 | } 90 | } 91 | } else { 92 | throw new \InvalidArgumentException("'$format' is not a valid format"); 93 | } 94 | } 95 | 96 | public static function decode($value, $format, $options) 97 | { 98 | $m = array(); 99 | if (preg_match(self::REGEX_VALID_FORMAT, $format, $m)) { 100 | if ($m['tipo1'] == 'X' && !$m['tipo2']) { 101 | return rtrim($value); 102 | } elseif ($m['tipo1'] == '9') { 103 | if ($m['tipo2'] == 'V9') { 104 | $tamanho_left = (int) $m['tamanho1']; 105 | $tamanho_right = (int) $m['tamanho2']; 106 | $valor_left = self::parseNumber(substr($value, 0, $tamanho_left)); 107 | $valor_right = '0.'.substr($value, $tamanho_left, $tamanho_right); 108 | if ((double) $valor_right > 0) { 109 | return $valor_left + (double) $valor_right; 110 | } else { 111 | return self::parseNumber($valor_left); 112 | } 113 | } elseif (!$m['tipo2']) { 114 | return self::parseNumber($value); 115 | } else { 116 | throw new \InvalidArgumentException("'$format' is not a valid format"); 117 | } 118 | } 119 | } else { 120 | throw new \InvalidArgumentException("'$format' is not a valid format"); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/Cnab/Format/YamlLoad.php: -------------------------------------------------------------------------------- 1 | codigo_banco = $codigo_banco; 18 | $this->layoutVersao = $layoutVersao; 19 | $this->formatPath = Factory::getCnabFormatPath(); 20 | } 21 | 22 | public function validateCollision($fields) 23 | { 24 | foreach ($fields as $name => $field) { 25 | $pos_start = $field['pos'][0]; 26 | $pos_end = $field['pos'][1]; 27 | 28 | foreach ($fields as $current_name => $current_field) { 29 | if ($current_name === $name) { 30 | continue; 31 | } 32 | 33 | $current_pos_start = $current_field['pos'][0]; 34 | $current_pos_end = $current_field['pos'][1]; 35 | 36 | if ($current_pos_start > $current_pos_end) { 37 | throw new \DomainException("No campo $current_name a posição inicial ($current_pos_start) deve ser menor ou igual à posição final ($current_pos_end)"); 38 | } 39 | 40 | if (($pos_start >= $current_pos_start && $pos_start <= $current_pos_end) || 41 | ($pos_end <= $current_pos_end && $pos_end >= $current_pos_start)) { 42 | throw new \DomainException("O campo $name colide com o campo $current_name"); 43 | } 44 | } 45 | 46 | return true; 47 | } 48 | } 49 | 50 | public function validateArray($array) 51 | { 52 | if (empty($array) || empty($array['generic'])) { 53 | throw new \Exception('arquivo yaml sem campo "generic"'); 54 | } 55 | 56 | foreach ($array as $key => $fields) { 57 | $this->validateCollision($fields); 58 | } 59 | 60 | return true; 61 | } 62 | 63 | public function loadArray(Linha $cnabLinha, $array) 64 | { 65 | $this->validateArray($array); 66 | 67 | $keys = array('generic'); 68 | if (array_key_exists(sprintf('%03d', $this->codigo_banco), $array)) { 69 | $keys[] = sprintf('%03d', $this->codigo_banco); 70 | } 71 | 72 | foreach ($array as $key => $fields) { 73 | if (in_array($key, $keys)) { 74 | foreach ($fields as $name => $info) { 75 | $picture = $info['picture']; 76 | $start = $info['pos'][0]; 77 | $end = $info['pos'][1]; 78 | $default = isset($info['default']) ? $info['default'] : false; 79 | $options = $info; 80 | 81 | $cnabLinha->addField($name, $start, $end, $picture, $default, $options); 82 | } 83 | } 84 | } 85 | } 86 | 87 | public function loadYaml($filename) 88 | { 89 | if (!isset(static::$loaded[$filename])) { 90 | if (!file_exists($filename)) { 91 | return; 92 | } 93 | static::$loaded[$filename] = spyc_load_file($filename); 94 | } 95 | return static::$loaded[$filename]; 96 | } 97 | 98 | public function loadFormat($cnab, $filename) 99 | { 100 | $banco = sprintf('%03d', $this->codigo_banco); 101 | $filenamePadrao = $this->formatPath.'/'.$cnab.'/generic/'.$filename.'.yml'; 102 | $filenameEspecifico = $this->formatPath.'/'.$cnab.'/'.$banco.'/'.$filename.'.yml'; 103 | 104 | if ($this->layoutVersao != null && $this->codigo_banco == 104) { 105 | // Usado quando o banco possuir mais de uma versao de Layout 106 | $filenameEspecifico = $this->formatPath.'/'.$cnab.'/'.$banco.'/'.$this->layoutVersao.'/'.$filename.'.yml'; 107 | } 108 | 109 | if (!file_exists($filenamePadrao) && !file_exists($filenameEspecifico)) { 110 | throw new \Exception('Arquivo não encontrado '.$filename); 111 | } 112 | 113 | $arrayPadrao = $this->loadYaml($filenamePadrao); 114 | $arrayEspecifico = $this->loadYaml($filenameEspecifico); 115 | 116 | $arrayFormat = array(); 117 | 118 | if ($arrayPadrao) { 119 | $arrayFormat['generic'] = $arrayPadrao; 120 | } 121 | 122 | if ($arrayEspecifico) { 123 | $arrayFormat[$banco] = $arrayEspecifico; 124 | } 125 | 126 | return $arrayFormat; 127 | } 128 | 129 | public function load(Linha $cnabLinha, $cnab, $filename) 130 | { 131 | $arrayFormat = $this->loadFormat($cnab, $filename); 132 | $this->loadArray($cnabLinha, $arrayFormat); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/Cnab/Instrucao.php: -------------------------------------------------------------------------------- 1 | codigo_banco = $codigo_banco; 24 | $this->layoutVersao = $layoutVersao; 25 | $this->banco = \Cnab\Banco::getBanco($this->codigo_banco); 26 | //$this->data_gravacao = date('dmY'); 27 | } 28 | 29 | public function configure(array $params) 30 | { 31 | $banco = \Cnab\Banco::getBanco($this->codigo_banco); 32 | $campos = array( 33 | 'data_geracao', 'data_gravacao', 'nome_fantasia', 'razao_social', 'cnpj', 'logradouro', 'numero', 'bairro', 34 | 'cidade', 'uf', 'cep', 35 | ); 36 | 37 | if ($this->codigo_banco == \Cnab\Banco::CEF) { 38 | $campos[] = 'codigo_cedente'; 39 | } 40 | 41 | if($this->codigo_banco == \Cnab\Banco::BANCO_DO_BRASIL) { 42 | $campos[] = 'codigo_convenio'; 43 | $campos[] = 'codigo_carteira'; 44 | $campos[] = 'variacao_carteira'; 45 | $campos[] = 'conta_dv'; 46 | } 47 | 48 | if ($this->codigo_banco == \Cnab\Banco::CEF || $this->codigo_banco == \Cnab\Banco::BANCO_DO_BRASIL) { 49 | $campos[] = 'agencia'; 50 | $campos[] = 'agencia_dv'; 51 | $campos[] = 'conta'; 52 | $campos[] = 'operacao'; 53 | $campos[] = 'numero_sequencial_arquivo'; 54 | } 55 | 56 | 57 | 58 | foreach ($campos as $campo) { 59 | if (array_key_exists($campo, $params)) { 60 | if (strpos($campo, 'data_') === 0 && !($params[$campo] instanceof \DateTime)) { 61 | throw new \Exception("config '$campo' need to be instance of DateTime"); 62 | } 63 | $this->configuracao[$campo] = $params[$campo]; 64 | } else { 65 | throw new \Exception('Configuração "'.$campo.'" need to be set'); 66 | } 67 | } 68 | 69 | foreach ($campos as $key) { 70 | if (!array_key_exists($key, $params)) { 71 | throw new Exception('Configuração "'.$key.'" dont exists'); 72 | } 73 | } 74 | 75 | $this->data_geracao = $this->configuracao['data_geracao']; 76 | $this->data_gravacao = $this->configuracao['data_gravacao']; 77 | 78 | $this->headerArquivo = new HeaderArquivo($this); 79 | $this->headerLote = new HeaderLote($this); 80 | $this->trailerLote = new TrailerLote($this); 81 | $this->trailerArquivo = new TrailerArquivo($this); 82 | 83 | $this->headerArquivo->codigo_banco = $this->banco['codigo_do_banco']; 84 | $this->headerArquivo->codigo_inscricao = 2; 85 | $this->headerArquivo->numero_inscricao = $this->prepareText($this->configuracao['cnpj'], '.-/'); 86 | $this->headerArquivo->agencia = $this->configuracao['agencia']; 87 | $this->headerArquivo->agencia_dv = $this->configuracao['agencia_dv']; 88 | 89 | if($this->codigo_banco == \Cnab\Banco::BANCO_DO_BRASIL) { 90 | $this->headerArquivo->codigo_convenio = $this->configuracao['codigo_convenio']; 91 | $this->headerArquivo->carteira = $this->configuracao['codigo_carteira']; 92 | $this->headerArquivo->variacao_carteira = $this->configuracao['variacao_carteira']; 93 | $this->headerArquivo->conta = $this->configuracao['conta']; 94 | $this->headerArquivo->conta_dv = $this->configuracao['conta_dv']; 95 | } 96 | 97 | if($this->codigo_banco == \Cnab\Banco::CEF) { 98 | $this->headerArquivo->codigo_cedente = $this->configuracao['codigo_cedente']; 99 | } 100 | 101 | $this->headerArquivo->nome_empresa = $this->configuracao['nome_fantasia']; 102 | $this->headerArquivo->nome_banco = $banco['nome_do_banco']; 103 | $this->headerArquivo->codigo_remessa_retorno = 1; 104 | $this->headerArquivo->data_geracao = $this->configuracao['data_geracao']; 105 | $this->headerArquivo->hora_geracao = $this->configuracao['data_geracao']; 106 | $this->headerArquivo->numero_sequencial_arquivo = $this->configuracao['numero_sequencial_arquivo']; 107 | 108 | if ($this->codigo_banco == \Cnab\Banco::CEF) { 109 | if($this->layoutVersao === 'sigcb') { 110 | $this->headerArquivo->codigo_convenio = 0; 111 | } else { 112 | $codigoConvenio = sprintf( 113 | '%04d%03d%08d', 114 | $params['agencia'], 115 | $params['operacao'], 116 | $params['conta'] 117 | ); 118 | $codigoConvenio .= $this->mod11($codigoConvenio); 119 | $this->headerArquivo->codigo_convenio = $codigoConvenio; 120 | } 121 | } 122 | 123 | $this->headerLote->codigo_banco = $this->headerArquivo->codigo_banco; 124 | $this->headerLote->lote_servico = 1; 125 | $this->headerLote->tipo_operacao = 'R'; 126 | $this->headerLote->codigo_inscricao = $this->headerArquivo->codigo_inscricao; 127 | $this->headerLote->numero_inscricao = $this->headerArquivo->numero_inscricao; 128 | $this->headerLote->agencia = $this->headerArquivo->agencia; 129 | $this->headerLote->agencia_dv = $this->headerArquivo->agencia_dv; 130 | 131 | 132 | if ($this->codigo_banco == \Cnab\Banco::CEF) { 133 | $this->headerLote->codigo_convenio = $this->headerArquivo->codigo_cedente; 134 | $this->headerLote->codigo_cedente = $this->headerArquivo->codigo_cedente; 135 | } 136 | 137 | if ($this->codigo_banco == \Cnab\Banco::BANCO_DO_BRASIL) { 138 | $this->headerLote->codigo_convenio = $this->headerArquivo->codigo_convenio; 139 | $this->headerLote->carteira = $this->headerArquivo->carteira; 140 | $this->headerLote->variacao_carteira = $this->headerArquivo->variacao_carteira; 141 | $this->headerLote->conta = $this->headerArquivo->conta; 142 | $this->headerLote->conta_dv = $this->headerArquivo->conta_dv; 143 | } 144 | 145 | $this->headerLote->nome_empresa = $this->headerArquivo->nome_empresa; 146 | $this->headerLote->numero_sequencial_arquivo = $this->headerArquivo->numero_sequencial_arquivo; 147 | $this->headerLote->data_geracao = $this->headerArquivo->data_geracao; 148 | 149 | if ($this->codigo_banco == \Cnab\Banco::CEF) { 150 | $this->headerLote->tipo_servico = 2; 151 | } 152 | 153 | $this->trailerLote->codigo_banco = $this->headerArquivo->codigo_banco; 154 | $this->trailerLote->lote_servico = $this->headerLote->lote_servico; 155 | 156 | $this->trailerArquivo->codigo_banco = $this->headerArquivo->codigo_banco; 157 | } 158 | 159 | public function mod11($num, $base = 9, $r = 0) 160 | { 161 | $soma = 0; 162 | $fator = 2; 163 | /* Separacao dos numeros */ 164 | for ($i = strlen($num); $i > 0; --$i) { 165 | // pega cada numero isoladamente 166 | $numeros[$i] = substr($num, $i - 1, 1); 167 | // Efetua multiplicacao do numero pelo falor 168 | $parcial[$i] = $numeros[$i] * $fator; 169 | // Soma dos digitos 170 | $soma += $parcial[$i]; 171 | if ($fator == $base) { // restaura fator de multiplicacao para 2 172 | $fator = 1; 173 | } 174 | ++$fator; 175 | } 176 | /* Calculo do modulo 11 */ 177 | if ($r == 0) { 178 | $soma *= 10; 179 | $digito = $soma % 11; 180 | if ($digito == 10) { 181 | $digito = 0; 182 | } 183 | 184 | return $digito; 185 | } elseif ($r == 1) { 186 | $resto = $soma % 11; 187 | 188 | return $resto; 189 | } 190 | } 191 | 192 | public function insertDetalhe(array $boleto, $tipo = 'remessa') 193 | { 194 | $dateVencimento = $boleto['data_vencimento'] instanceof \DateTime ? $boleto['data_vencimento'] : new \DateTime($boleto['data_vencimento']); 195 | $dateCadastro = $boleto['data_cadastro'] instanceof \DateTime ? $boleto['data_cadastro'] : new \DateTime($boleto['data_cadastro']); 196 | $dateJurosMora = clone $dateVencimento; 197 | 198 | $detalhe = new Detalhe($this); 199 | 200 | // SEGMENTO P ------------------------------- 201 | $detalhe->segmento_p->codigo_banco = $this->headerArquivo->codigo_banco; 202 | $detalhe->segmento_p->lote_servico = $this->headerLote->lote_servico; 203 | $detalhe->segmento_p->agencia = $this->headerArquivo->agencia; 204 | $detalhe->segmento_p->agencia_dv = $this->headerArquivo->agencia_dv; 205 | 206 | if ($this->codigo_banco == \Cnab\Banco::CEF) { 207 | $detalhe->segmento_p->codigo_cedente = $this->headerArquivo->codigo_cedente; 208 | } 209 | 210 | if ($this->codigo_banco == \Cnab\Banco::BANCO_DO_BRASIL) { 211 | $detalhe->segmento_p->conta = $this->headerArquivo->conta; 212 | $detalhe->segmento_p->conta_dv = $this->headerArquivo->conta_dv; 213 | } 214 | 215 | $detalhe->segmento_p->nosso_numero = $this->formatarNossoNumero($boleto['nosso_numero']); 216 | 217 | if($this->codigo_banco == \Cnab\Banco::BANCO_DO_BRASIL) { 218 | // Informar 1 – para carteira 11/12 na modalidade Simples; 2 ou 3 – para carteira 11/17 modalidade 219 | // Vinculada/Caucionada e carteira 31; 4 – para carteira 11/17 modalidade Descontada e carteira 51; e 7 – para 220 | // carteira 17 modalidade Simples. 221 | if($boleto['carteira'] == 17 && $boleto['codigo_carteira'] == \Cnab\CodigoCarteira::COBRANCA_SIMPLES) { 222 | $detalhe->segmento_p->codigo_carteira = 7; 223 | } else { 224 | $detalhe->segmento_p->codigo_carteira = $boleto['codigo_carteira']; 225 | } 226 | } 227 | 228 | if ($this->layoutVersao === 'sigcb' && $this->codigo_banco == \Cnab\Banco::CEF) { 229 | $detalhe->segmento_p->codigo_carteira = 1; // 1 = Cobrança Simples 230 | $detalhe->segmento_p->modalidade_carteira = $boleto['modalidade_carteira']; // 21 = (título Sem Registro emissão CAIXA) 231 | } 232 | 233 | $detalhe->segmento_p->forma_cadastramento = $boleto['registrado'] ? 1 : 2; // 1 = Com, 2 = Sem Registro 234 | if ($boleto['registrado'] && $this->codigo_banco == \Cnab\Banco::CEF) { 235 | $this->headerLote->tipo_servico = 1; 236 | } 237 | $detalhe->segmento_p->numero_documento = $boleto['numero_documento']; 238 | $detalhe->segmento_p->vencimento = $dateVencimento; 239 | $detalhe->segmento_p->valor_titulo = $boleto['valor']; 240 | $detalhe->segmento_p->especie = $boleto['especie']; // 4 = Duplicata serviço 241 | $detalhe->segmento_p->aceite = $boleto['aceite']; 242 | $detalhe->segmento_p->data_emissao = $dateCadastro; 243 | $detalhe->segmento_p->codigo_juros_mora = isset($boleto['codigo_juros_mora'])?$boleto['codigo_juros_mora']:1; // 1 = Por dia, 2= Taxa Mensal, 3= Isento 244 | 245 | if (!empty($boleto['dias_iniciar_contagem_juros']) && is_numeric($boleto['dias_iniciar_contagem_juros'])) { 246 | $dateJurosMora->modify("+{$boleto['dias_iniciar_contagem_juros']} days"); 247 | } else { 248 | $dateJurosMora->modify('+1 day'); 249 | } 250 | 251 | $detalhe->segmento_p->data_juros_mora = $dateJurosMora; 252 | 253 | $detalhe->segmento_p->valor_juros_mora = $boleto['juros_de_um_dia']; 254 | if ($boleto['valor_desconto'] > 0) { 255 | $detalhe->segmento_p->codigo_desconto_1 = 1; // valor fixo 256 | $detalhe->segmento_p->data_desconto_1 = $boleto['data_desconto']; 257 | $detalhe->segmento_p->valor_desconto_1 = $boleto['valor_desconto']; 258 | } else { 259 | $detalhe->segmento_p->codigo_desconto_1 = 0; // sem desconto 260 | $detalhe->segmento_p->data_desconto_1 = 0; 261 | $detalhe->segmento_p->valor_desconto_1 = 0; 262 | } 263 | $detalhe->segmento_p->valor_abatimento = 0; 264 | $detalhe->segmento_p->uso_empresa = $boleto['numero_documento']; 265 | 266 | if (!empty($boleto['codigo_protesto']) && !empty($boleto['prazo_protesto'])) { 267 | $detalhe->segmento_p->codigo_protesto = $boleto['codigo_protesto']; 268 | $detalhe->segmento_p->prazo_protesto = $boleto['prazo_protesto']; 269 | } else { 270 | $detalhe->segmento_p->codigo_protesto = 3; // 3 = Não protestar 271 | $detalhe->segmento_p->prazo_protesto = 0; 272 | } 273 | 274 | if ($this->codigo_banco == \Cnab\Banco::BANCO_DO_BRASIL) { 275 | // Campo não tratado pelo sistema. Informar 'zeros'. 276 | // O sistema considera a informação que foi cadastrada na 277 | // sua carteira junto ao Banco do Brasil. 278 | $detalhe->segmento_p->codigo_baixa = 0; 279 | $detalhe->segmento_p->prazo_baixa = 0; 280 | } else { 281 | if(isset($boleto['baixar_apos_dias'])) { 282 | if($boleto['baixar_apos_dias'] === false) { 283 | // não baixar / devolver 284 | $detalhe->segmento_p->codigo_baixa = 2; 285 | $detalhe->segmento_p->prazo_baixa = 0; 286 | } else { 287 | // baixa automática 288 | $detalhe->segmento_p->codigo_baixa = 1; 289 | $detalhe->segmento_p->prazo_baixa = $boleto['baixar_apos_dias']; 290 | } 291 | } else { 292 | $detalhe->segmento_p->codigo_baixa = 0; 293 | $detalhe->segmento_p->prazo_baixa = 0; 294 | } 295 | } 296 | 297 | if (array_key_exists('identificacao_distribuicao', $boleto)) { 298 | $detalhe->segmento_p->identificacao_distribuicao = $boleto['identificacao_distribuicao']; 299 | } 300 | 301 | if ($tipo == 'remessa') { 302 | $detalhe->segmento_p->codigo_ocorrencia = 1; 303 | } elseif ($tipo == 'baixa') { 304 | $detalhe->segmento_p->codigo_ocorrencia = 2; 305 | } else { 306 | throw new \Exception('Tipo de detalhe inválido: '.$tipo); 307 | } 308 | 309 | // SEGMENTO Q ------------------------------- 310 | $detalhe->segmento_q->codigo_banco = $this->headerArquivo->codigo_banco; 311 | $detalhe->segmento_q->lote_servico = $this->headerLote->lote_servico; 312 | $detalhe->segmento_q->codigo_ocorrencia = $detalhe->segmento_p->codigo_ocorrencia; 313 | if (@$boleto['sacado_cnpj']) { 314 | $detalhe->segmento_q->sacado_codigo_inscricao = '2'; 315 | $detalhe->segmento_q->sacado_numero_inscricao = $this->prepareText($boleto['sacado_cnpj'], '.-/'); 316 | $detalhe->segmento_q->nome = $this->prepareText($boleto['sacado_razao_social']); 317 | } else { 318 | $detalhe->segmento_q->sacado_codigo_inscricao = '1'; 319 | $detalhe->segmento_q->sacado_numero_inscricao = $this->prepareText($boleto['sacado_cpf'], '.-/'); 320 | $detalhe->segmento_q->nome = $this->prepareText($boleto['sacado_nome']); 321 | } 322 | $detalhe->segmento_q->logradouro = $this->prepareText($boleto['sacado_logradouro']); 323 | $detalhe->segmento_q->bairro = $this->prepareText($boleto['sacado_bairro']); 324 | $detalhe->segmento_q->cep = str_replace('-', '', $boleto['sacado_cep']); 325 | $detalhe->segmento_q->cidade = $this->prepareText($boleto['sacado_cidade']); 326 | $detalhe->segmento_q->estado = $boleto['sacado_uf']; 327 | // se o titulo for de terceiro, o sacador é o terceiro 328 | $detalhe->segmento_q->sacador_codigo_inscricao = $this->headerArquivo->codigo_inscricao; 329 | $detalhe->segmento_q->sacador_numero_inscricao = $this->headerArquivo->numero_inscricao; 330 | $detalhe->segmento_q->sacador_nome = $this->headerArquivo->nome_empresa; 331 | 332 | // SEGMENTO R ------------------------------- 333 | $detalhe->segmento_r->codigo_banco = $detalhe->segmento_p->codigo_banco; 334 | $detalhe->segmento_r->lote_servico = $detalhe->segmento_p->lote_servico; 335 | $detalhe->segmento_r->codigo_ocorrencia = $detalhe->segmento_p->codigo_ocorrencia; 336 | if ($boleto['valor_multa'] > 0) { 337 | $detalhe->segmento_r->codigo_multa = 1; 338 | $detalhe->segmento_r->valor_multa = $boleto['valor_multa']; 339 | $detalhe->segmento_r->data_multa = $boleto['data_multa']; 340 | } else { 341 | $detalhe->segmento_r->codigo_multa = 0; 342 | $detalhe->segmento_r->valor_multa = 0; 343 | $detalhe->segmento_r->data_multa = 0; 344 | } 345 | 346 | $this->detalhes[] = $detalhe; 347 | } 348 | 349 | public function formatarNossoNumero($nossoNumero) 350 | { 351 | if(!$nossoNumero) 352 | return $nossoNumero; 353 | 354 | if ($this->codigo_banco == \Cnab\Banco::BANCO_DO_BRASIL) { 355 | $codigo_convenio = $this->configuracao['codigo_convenio']; 356 | 357 | if(strlen($codigo_convenio) <= 4) { 358 | # Convênio de 4 digitos 359 | if(strlen($nossoNumero) > 7) { 360 | throw new \InvalidArgumentException( 361 | "Para número de convênio de 4 posições o nosso número deve ter no máximo 7 posições (sem o digito)" 362 | ); 363 | } 364 | $number = sprintf('%04d%07d', $codigo_convenio, $nossoNumero); 365 | return $number . $this->mod11($number); 366 | } elseif (strlen($codigo_convenio) <= 6) { 367 | # Convênio de 6 digitos 368 | if(strlen($nossoNumero) > 5) { 369 | throw new \InvalidArgumentException( 370 | "Para número de convênio de 6 posições o nosso número deve ter no máximo 5 posições (sem o digito)" 371 | ); 372 | } 373 | $number = sprintf('%06d%05d', $codigo_convenio, $nossoNumero); 374 | return $number . $this->mod11($number); 375 | } else { 376 | if(strlen($nossoNumero) > 10) { 377 | throw new \InvalidArgumentException( 378 | "Para número de convênio de 7 posições o nosso número deve ter no máximo 10 posições" 379 | ); 380 | } 381 | $number = sprintf('%07d%010d', $codigo_convenio, $nossoNumero); 382 | return $number; 383 | } 384 | } 385 | 386 | return $nossoNumero; 387 | } 388 | 389 | public function listDetalhes() 390 | { 391 | return $this->detalhes; 392 | } 393 | 394 | private function prepareText($text, $remove = null) 395 | { 396 | $result = strtoupper($this->removeAccents(trim(html_entity_decode($text)))); 397 | if ($remove) { 398 | $result = str_replace(str_split($remove), '', $result); 399 | } 400 | 401 | return $result; 402 | } 403 | 404 | private function removeAccents($string) 405 | { 406 | return preg_replace( 407 | array( 408 | '/\xc3[\x80-\x85]/', 409 | '/\xc3\x87/', 410 | '/\xc3[\x88-\x8b]/', 411 | '/\xc3[\x8c-\x8f]/', 412 | '/\xc3([\x92-\x96]|\x98)/', 413 | '/\xc3[\x99-\x9c]/', 414 | 415 | '/\xc3[\xa0-\xa5]/', 416 | '/\xc3\xa7/', 417 | '/\xc3[\xa8-\xab]/', 418 | '/\xc3[\xac-\xaf]/', 419 | '/\xc3([\xb2-\xb6]|\xb8)/', 420 | '/\xc3[\xb9-\xbc]/', 421 | '/\xC2\xAA/', 422 | '/\xC2\xBA/', 423 | ), 424 | str_split('ACEIOUaceiouao', 1), 425 | $this->isUtf8($string) ? $string : utf8_encode($string) 426 | ); 427 | } 428 | 429 | private function isUtf8($string) 430 | { 431 | return preg_match('%^(?: 432 | [\x09\x0A\x0D\x20-\x7E] 433 | | [\xC2-\xDF][\x80-\xBF] 434 | | \xE0[\xA0-\xBF][\x80-\xBF] 435 | | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} 436 | | \xED[\x80-\x9F][\x80-\xBF] 437 | | \xF0[\x90-\xBF][\x80-\xBF]{2} 438 | | [\xF1-\xF3][\x80-\xBF]{3} 439 | | \xF4[\x80-\x8F][\x80-\xBF]{2} 440 | )*$%xs', 441 | $string 442 | ); 443 | } 444 | 445 | public function getText() 446 | { 447 | $numero_sequencial_lote = 1; 448 | $qtde_registro_lote = 2; // header e trailer = 2 449 | $qtde_titulo_cobranca_simples = 0; 450 | $valor_total_titulo_simples = 0; 451 | 452 | // valida os dados 453 | if (!$this->headerArquivo->validate()) { 454 | throw new \InvalidArgumentException($this->headerArquivo->last_error); 455 | } 456 | 457 | if (!$this->headerLote->validate()) { 458 | throw new \InvalidArgumentException($this->headerLote->last_error); 459 | } 460 | 461 | $dados = $this->headerArquivo->getEncoded().self::QUEBRA_LINHA; 462 | $dados .= $this->headerLote->getEncoded().self::QUEBRA_LINHA; 463 | 464 | foreach ($this->detalhes as $detalhe) { 465 | ++$qtde_titulo_cobranca_simples; 466 | $valor_total_titulo_simples += $detalhe->segmento_p->valor_titulo; 467 | foreach ($detalhe->listSegmento() as $segmento) { 468 | ++$qtde_registro_lote; 469 | $segmento->numero_sequencial_lote = $numero_sequencial_lote++; 470 | } 471 | 472 | if (!$detalhe->validate()) { 473 | throw new \InvalidArgumentException($detalhe->last_error); 474 | } 475 | 476 | $dados .= $detalhe->getEncoded().self::QUEBRA_LINHA; 477 | } 478 | 479 | $this->trailerLote->qtde_registro_lote = $qtde_registro_lote; 480 | 481 | if ($this->codigo_banco == \Cnab\Banco::CEF) { 482 | $this->trailerLote->qtde_titulo_cobranca_simples = $qtde_titulo_cobranca_simples; 483 | $this->trailerLote->valor_total_titulo_simples = $valor_total_titulo_simples; 484 | $this->trailerLote->qtde_titulo_cobranca_caucionada = 0; 485 | $this->trailerLote->valor_total_titulo_caucionada = 0; 486 | $this->trailerLote->qtde_titulo_cobranca_descontada = 0; 487 | $this->trailerLote->valor_total_titulo_descontada = 0; 488 | } 489 | 490 | $this->trailerArquivo->qtde_lotes = 1; 491 | $this->trailerArquivo->qtde_registros = $this->trailerLote->qtde_registro_lote + 2; 492 | 493 | if (!$this->trailerLote->validate()) { 494 | throw new \InvalidArgumentException($this->trailerLote->last_error); 495 | } 496 | 497 | if (!$this->trailerArquivo->validate()) { 498 | throw new \InvalidArgumentException($this->trailerArquivo->last_error); 499 | } 500 | 501 | $dados .= $this->trailerLote->getEncoded().self::QUEBRA_LINHA; 502 | $dados .= $this->trailerArquivo->getEncoded().self::QUEBRA_LINHA; 503 | 504 | return $dados; 505 | } 506 | 507 | public function countDetalhes() 508 | { 509 | return count($this->detalhes); 510 | } 511 | 512 | public function save($filename) 513 | { 514 | $text = $this->getText(); 515 | 516 | file_put_contents($filename, $text); 517 | 518 | return $filename; 519 | } 520 | } 521 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab240/Detalhe.php: -------------------------------------------------------------------------------- 1 | segmento_p = new SegmentoP($arquivo); 16 | $this->segmento_q = new SegmentoQ($arquivo); 17 | $this->segmento_r = new SegmentoR($arquivo); 18 | } 19 | 20 | public function validate() 21 | { 22 | $this->last_error = null; 23 | foreach ($this->listSegmento() as $segmento) { 24 | if (!$segmento->validate()) { 25 | $this->last_error = get_class($segmento).': '.$segmento->last_error; 26 | } 27 | } 28 | 29 | return is_null($this->last_error); 30 | } 31 | 32 | /** 33 | * Lista todos os segmentos deste detalhe. 34 | * 35 | * @return array 36 | */ 37 | public function listSegmento() 38 | { 39 | return array( 40 | $this->segmento_p, 41 | $this->segmento_q, 42 | $this->segmento_r, 43 | ); 44 | } 45 | 46 | /** 47 | * Retorna todas as linhas destes detalhes. 48 | * 49 | * @return string 50 | */ 51 | public function getEncoded() 52 | { 53 | $text = array(); 54 | foreach ($this->listSegmento() as $segmento) { 55 | $text[] = $segmento->getEncoded(); 56 | } 57 | 58 | return implode(Arquivo::QUEBRA_LINHA, $text); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab240/HeaderArquivo.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'header_arquivo'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab240/HeaderLote.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'header_lote'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab240/SegmentoP.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'remessa/detalhe_segmento_p'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab240/SegmentoQ.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'remessa/detalhe_segmento_q'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab240/SegmentoR.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'remessa/detalhe_segmento_r'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab240/TrailerArquivo.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'trailer_arquivo'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab240/TrailerLote.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'trailer_lote'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab400/Arquivo.php: -------------------------------------------------------------------------------- 1 | codigo_banco = $codigo_banco; 21 | $this->layout_versao = $layout_versao; 22 | $this->banco = \Cnab\Banco::getBanco($this->codigo_banco); 23 | //$this->data_gravacao = date('dmY'); 24 | } 25 | 26 | public function configure(array $params) 27 | { 28 | $campos = array( 29 | 'data_geracao', 'data_gravacao', 'nome_fantasia', 'razao_social', 'cnpj', 'logradouro', 'numero', 'bairro', 30 | 'cidade', 'uf', 'cep', 'agencia', 'conta' 31 | ); 32 | 33 | switch ($this->codigo_banco) { 34 | case \Cnab\Banco::CEF: 35 | $campos[] = 'operacao'; 36 | $campos[] = 'codigo_cedente'; 37 | $campos[] = 'codigo_cedente_dac'; 38 | case \Cnab\Banco::BRADESCO: 39 | $campos[] = 'codigo_cedente'; 40 | $campos[] = 'sequencial_remessa'; 41 | break; 42 | case \Cnab\Banco::BANCO_DO_BRASIL: 43 | $campos[] = 'agencia_dac'; 44 | $campos[] = 'conta_dac'; 45 | $campos[] = 'numero_sequencial'; 46 | $campos[] = 'numero_convenio'; 47 | break; 48 | default: 49 | $campos[] = 'conta_dac'; 50 | break; 51 | } 52 | 53 | foreach ($campos as $campo) { 54 | if (array_key_exists($campo, $params)) { 55 | if (strpos($campo, 'data_') === 0 && !($params[$campo] instanceof \DateTime)) { 56 | throw new \Exception("config '$campo' need to be instance of DateTime"); 57 | } 58 | $this->configuracao[$campo] = $params[$campo]; 59 | } else { 60 | throw new \Exception('Configuração "'.$campo.'" need to be set'); 61 | } 62 | } 63 | 64 | foreach ($campos as $key) { 65 | if (!array_key_exists($key, $params)) { 66 | throw new Exception('Configuração "'.$key.'" dont exists'); 67 | } 68 | } 69 | 70 | $this->data_geracao = $this->configuracao['data_geracao']; 71 | $this->data_gravacao = $this->configuracao['data_gravacao']; 72 | 73 | $this->header = new Header($this); 74 | 75 | $this->header->codigo_banco = $this->banco['codigo_do_banco']; 76 | $this->header->nome_banco = $this->banco['nome_do_banco']; 77 | $this->header->agencia = $this->configuracao['agencia']; 78 | $this->header->conta = $this->configuracao['conta']; 79 | 80 | switch ($this->codigo_banco) { 81 | case \Cnab\Banco::CEF: 82 | $this->header->codigo_cedente = $this->configuracao['codigo_cedente']; 83 | case \Cnab\Banco::BRADESCO: 84 | $this->header->codigo_cedente = $this->configuracao['codigo_cedente']; 85 | $this->header->sequencial_remessa = $this->configuracao['sequencial_remessa']; 86 | $this->header->razao_social = $this->configuracao['razao_social']; 87 | break; 88 | case \Cnab\Banco::BANCO_DO_BRASIL: 89 | $this->header->agencia_dv = $this->configuracao['agencia_dac']; 90 | $this->header->conta_dv = $this->configuracao['conta_dac']; 91 | $this->header->numero_sequencial = $this->configuracao['numero_sequencial']; 92 | $this->header->convenio_lider = $this->configuracao['numero_convenio']; 93 | break; 94 | default: 95 | $this->header->conta_dv = $this->configuracao['conta_dac']; 96 | break; 97 | } 98 | 99 | $this->header->nome_empresa = $this->configuracao['nome_fantasia']; 100 | $this->header->data_geracao = $this->configuracao['data_geracao']->format('dmy'); 101 | } 102 | 103 | public function insertDetalhe(array $boleto, $tipo = 'remessa') 104 | { 105 | $dateVencimento = $boleto['data_vencimento'] instanceof \DateTime ? $boleto['data_vencimento'] : new \DateTime($boleto['data_vencimento']); 106 | $dateCadastro = $boleto['data_cadastro'] instanceof \DateTime ? $boleto['data_cadastro'] : new \DateTime($boleto['data_cadastro']); 107 | 108 | $detalhe = new Detalhe($this); 109 | $complementos = array(); 110 | 111 | if ($tipo == 'remessa') { 112 | $detalhe->codigo_ocorrencia = !empty($boleto['codigo_de_ocorrencia']) ? $boleto['codigo_de_ocorrencia'] : '1'; 113 | 114 | $detalhe->codigo_inscricao = 2; 115 | $detalhe->numero_inscricao = $this->prepareText($this->configuracao['cnpj'], '.-/'); 116 | 117 | if (\Cnab\Banco::BRADESCO == $this->codigo_banco) { 118 | $detalhe->codigo_cedente = $this->header->codigo_cedente; 119 | $detalhe->digito_nosso_numero = $boleto['digito_nosso_numero']; 120 | } else if (\Cnab\Banco::CEF == $this->codigo_banco) { 121 | $detalhe->codigo_cedente = $this->header->codigo_cedente; 122 | $detalhe->taxa_de_permanencia = $boleto['taxa_de_permanencia']; 123 | $detalhe->mensagem = $boleto['mensagem']; 124 | $detalhe->data_multa = $boleto['data_multa']; 125 | $detalhe->valor_multa = $boleto['valor_multa']; 126 | } else if (\Cnab\Banco::BANCO_DO_BRASIL == $this->codigo_banco) { 127 | $detalhe->agencia = $this->header->agencia; 128 | $detalhe->agencia_dv = $this->header->agencia_dv; 129 | $detalhe->conta = $this->header->conta; 130 | $detalhe->conta_dv = $this->header->conta_dv; 131 | $detalhe->numero_convenio = $boleto['numero_convenio']; 132 | $detalhe->variacao_carteira = $boleto['variacao_carteira']; 133 | $detalhe->tipo_cobranca = (isset($boleto['tipo_cobranca']) ?: ''); 134 | 135 | } else { 136 | $detalhe->agencia = $this->header->agencia; 137 | $detalhe->conta = $this->header->conta; 138 | $detalhe->conta_dv = $this->header->conta_dv; 139 | $detalhe->codigo_instrucao = '0'; 140 | $detalhe->qtde_moeda = '0'; # Este campo deverá ser preenchido com zeros caso a moeda seja o Real. 141 | $detalhe->codigo_carteira = 'I'; 142 | $detalhe->uso_banco = ''; 143 | $detalhe->data_mora = $boleto['data_multa']; 144 | 145 | if ($boleto['valor_multa'] > 0) { 146 | /* 147 | // Não está presente na documentação disponibilizada no site 148 | // os valores de multa devem ser configurados com o gerente da sua conta 149 | $detalheMulta = new DetalheMulta($this); 150 | if(@$boleto['tipo_multa'] == 'porcentagem') 151 | $detalheMulta->codigo_multa = 2; 152 | else if(!@$boleto['tipo_multa'] || $boleto['tipo_multa'] == 'valor') 153 | $detalheMulta->codigo_multa = 1; 154 | else 155 | throw new Exception('tipo de multa inválido, deve ser "porcentagem" ou "valor"'); 156 | $detalheMulta->data_multa = $boleto['data_multa']; 157 | $detalheMulta->valor_multa = $boleto['valor_multa']; 158 | $complementos[] = $detalheMulta; 159 | */ 160 | } 161 | } 162 | 163 | /* 164 | Deve ser preenchido na remessa somente quando utilizados, na posição 109-110, os códigos de 165 | ocorrência 35 – Cancelamento de Instrução e 38 – Cedente não concorda com alegação do sacado. Para 166 | os demais códigos de ocorrência este campo deverá ser preenchido com zeros. 167 | */ 168 | $detalhe->uso_empresa = isset($boleto['uso_empresa']) 169 | ? $boleto['uso_empresa'] 170 | : $boleto['nosso_numero']; 171 | $detalhe->nosso_numero = $boleto['nosso_numero']; 172 | 173 | $detalhe->numero_carteira = $boleto['carteira']; 174 | $detalhe->numero_documento = $boleto['numero_documento']; 175 | $detalhe->vencimento = $dateVencimento->format('dmy'); 176 | $detalhe->valor_titulo = $boleto['valor']; 177 | $detalhe->aceite = empty($boleto['aceite']) ? 'N' : $boleto['aceite']; 178 | $detalhe->instrucao1 = $boleto['instrucao1']; 179 | $detalhe->instrucao2 = $boleto['instrucao2']; 180 | $detalhe->especie = $boleto['especie']; 181 | $detalhe->data_emissao = $dateCadastro->format('dmy'); 182 | 183 | $sacado_tipo = @$boleto['sacado_tipo'] or $sacado_tipo = 'cpf'; 184 | 185 | if ($sacado_tipo == 'cnpj') { 186 | $detalhe->sacado_codigo_inscricao = '2'; 187 | /* 188 | * @todo Trocar espécie 189 | */ 190 | $detalhe->sacado_numero_inscricao = $this->prepareText($boleto['sacado_cnpj'], '.-/'); 191 | $detalhe->nome = $this->prepareText($boleto['sacado_razao_social']); 192 | } else { 193 | $detalhe->sacado_codigo_inscricao = '1'; 194 | /* 195 | * @todo Trocar espécie 196 | */ 197 | $detalhe->sacado_numero_inscricao = $this->prepareText($boleto['sacado_cpf'], '.-/'); 198 | $detalhe->nome = $this->prepareText($boleto['sacado_nome']); 199 | } 200 | 201 | $detalhe->logradouro = $this->prepareText($boleto['sacado_logradouro']); 202 | $detalhe->bairro = $this->prepareText($boleto['sacado_bairro']); 203 | $detalhe->cep = str_replace('-', '', $boleto['sacado_cep']); 204 | $detalhe->cidade = $this->prepareText($boleto['sacado_cidade']); 205 | $detalhe->estado = $boleto['sacado_uf']; 206 | $detalhe->sacador = $this->prepareText($this->configuracao['nome_fantasia']); 207 | 208 | $detalhe->juros_um_dia = $boleto['juros_de_um_dia']; 209 | $detalhe->desconto_ate = $boleto['data_desconto']; 210 | $detalhe->valor_desconto = $boleto['valor_desconto']; 211 | $detalhe->prazo = $boleto['prazo']; 212 | } elseif ($tipo == 'baixa') { 213 | $detalhe->codigo_inscricao = '0'; 214 | $detalhe->numero_inscricao = '0'; 215 | $detalhe->agencia = $this->header->agencia; 216 | $detalhe->conta = $this->header->conta; 217 | $detalhe->conta_dac = $this->header->dac; 218 | $detalhe->codigo_instrucao = '0'; 219 | /* 220 | Deve ser preenchido na remessa somente quando utilizados, na posição 109-110, os códigos de 221 | ocorrência 35 – Cancelamento de Instrução e 38 – Cedente não concorda com alegação do sacado. Para 222 | os demais códigos de ocorrência este campo deverá ser preenchido com zeros. 223 | */ 224 | $detalhe->codigo_ocorrencia = $boleto['codigo_de_ocorrencia']; 225 | $detalhe->uso_empresa = $boleto['nosso_numero']; 226 | $detalhe->nosso_numero = $boleto['nosso_numero']; 227 | $detalhe->qtde_moeda = '0'; # Este campo deverá ser preenchido com zeros caso a moeda seja o Real. 228 | $detalhe->numero_carteira = $boleto['carteira']; 229 | $detalhe->codigo_carteira = 'I'; 230 | $detalhe->uso_banco = ''; 231 | $detalhe->numero_documento = $boleto['numero_documento']; 232 | $detalhe->vencimento = '0'; 233 | $detalhe->valor_titulo = $boleto['valor']; 234 | $detalhe->aceite = ' '; 235 | $detalhe->data_emissao = '0'; 236 | $detalhe->sacado_codigo_inscricao = '2'; 237 | $detalhe->especie = ' '; 238 | $detalhe->sacado_numero_inscricao = '0'; 239 | $detalhe->juros_um_dia = $boleto['juros_de_um_dia']; 240 | $detalhe->data_juros = $boleto['data_juros']; 241 | 242 | $detalhe->nome = ' '; 243 | $detalhe->logradouro = ' '; 244 | $detalhe->bairro = ' '; 245 | $detalhe->cep = '0'; 246 | $detalhe->cidade = ' '; 247 | $detalhe->estado = ' '; 248 | $detalhe->sacador = ' '; 249 | } else { 250 | throw new Exception('Tipo de $detalhe desconhecido'); 251 | } 252 | 253 | $detalhe->codigo_banco = $this->banco['codigo_do_banco']; 254 | 255 | $this->detalhes[] = $detalhe; 256 | 257 | foreach ($complementos as $complemento) { 258 | $this->detalhes[] = $complemento; 259 | } 260 | } 261 | 262 | public function listDetalhes() 263 | { 264 | return $this->detalhes; 265 | } 266 | 267 | private function prepareText($text, $remove = null) 268 | { 269 | $result = strtoupper($this->removeAccents(trim(html_entity_decode($text)))); 270 | if ($remove) { 271 | $result = str_replace(str_split($remove), '', $result); 272 | } 273 | 274 | return $result; 275 | } 276 | 277 | private function removeAccents($string) 278 | { 279 | return preg_replace( 280 | array( 281 | '/\xc3[\x80-\x85]/', 282 | '/\xc3\x87/', 283 | '/\xc3[\x88-\x8b]/', 284 | '/\xc3[\x8c-\x8f]/', 285 | '/\xc3([\x92-\x96]|\x98)/', 286 | '/\xc3[\x99-\x9c]/', 287 | 288 | '/\xc3[\xa0-\xa5]/', 289 | '/\xc3\xa7/', 290 | '/\xc3[\xa8-\xab]/', 291 | '/\xc3[\xac-\xaf]/', 292 | '/\xc3([\xb2-\xb6]|\xb8)/', 293 | '/\xc3[\xb9-\xbc]/', 294 | ), 295 | str_split('ACEIOUaceiou', 1), 296 | $this->isUtf8($string) ? $string : utf8_encode($string) 297 | ); 298 | } 299 | 300 | private function isUtf8($string) 301 | { 302 | return preg_match('%^(?: 303 | [\x09\x0A\x0D\x20-\x7E] 304 | | [\xC2-\xDF][\x80-\xBF] 305 | | \xE0[\xA0-\xBF][\x80-\xBF] 306 | | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} 307 | | \xED[\x80-\x9F][\x80-\xBF] 308 | | \xF0[\x90-\xBF][\x80-\xBF]{2} 309 | | [\xF1-\xF3][\x80-\xBF]{3} 310 | | \xF4[\x80-\x8F][\x80-\xBF]{2} 311 | )*$%xs', 312 | $string 313 | ); 314 | } 315 | 316 | public function __set($name, $value) 317 | { 318 | if (strpos($name, 'data_') === 0) { 319 | if ($value instanceof \DateTime) { 320 | $property = "_$name"; 321 | $this->$property = $value; 322 | } else { 323 | throw new InvalidArgumentException("$nome need to be instance of DateTime"); 324 | } 325 | } else { 326 | throw new Exception("property '$name' dont exists"); 327 | } 328 | } 329 | 330 | public function getText() 331 | { 332 | $numero_sequencial = 1; 333 | 334 | $this->header->numero_sequencial = $numero_sequencial++; 335 | 336 | // valida os dados 337 | if (!$this->header->validate()) { 338 | throw new \InvalidArgumentException($this->header->last_error); 339 | } 340 | 341 | $dados = $this->header->getEncoded().self::QUEBRA_LINHA; 342 | $this->trailer = new Trailer($this); 343 | foreach ($this->detalhes as $detalhe) { 344 | $detalhe->numero_sequencial = $numero_sequencial++; 345 | if (!$detalhe->validate()) { 346 | throw new \InvalidArgumentException($detalhe->last_error); 347 | } 348 | 349 | $dados .= $detalhe->getEncoded().self::QUEBRA_LINHA; 350 | } 351 | $this->trailer->numero_sequencial = $numero_sequencial++; 352 | 353 | if (!$this->trailer->validate()) { 354 | throw new \InvalidArgumentException($this->trailer->last_error); 355 | } 356 | 357 | $dados .= $this->trailer->getEncoded().self::QUEBRA_LINHA; 358 | 359 | return $dados; 360 | } 361 | 362 | public function countDetalhes() 363 | { 364 | return count($this->detalhes); 365 | } 366 | 367 | public function save($filename) 368 | { 369 | $text = $this->getText(); 370 | file_put_contents($filename, $text); 371 | } 372 | } 373 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab400/Detalhe.php: -------------------------------------------------------------------------------- 1 | codigo_banco; 10 | $yamlLoad = new \Cnab\Format\YamlLoad($codigo_banco); 11 | $yamlLoad->load($this, 'cnab400', 'remessa/detalhe'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab400/DetalheMulta.php: -------------------------------------------------------------------------------- 1 | codigo_banco; 10 | $yamlLoad = new \Cnab\Format\YamlLoad($codigo_banco); 11 | $yamlLoad->load($this, 'cnab400', 'remessa/detalhe_multa'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab400/Header.php: -------------------------------------------------------------------------------- 1 | codigo_banco; 10 | $yamlLoad = new \Cnab\Format\YamlLoad($codigo_banco); 11 | $yamlLoad->load($this, 'cnab400', 'remessa/header_arquivo'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/Cnab400/Trailer.php: -------------------------------------------------------------------------------- 1 | codigo_banco; 10 | $yamlLoad = new \Cnab\Format\YamlLoad($codigo_banco); 11 | $yamlLoad->load($this, 'cnab400', 'remessa/trailer_arquivo'); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Cnab/Remessa/IArquivo.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 24 | $this->layoutVersao = $layoutVersao; 25 | 26 | if (!file_exists($this->filename)) { 27 | throw new \Exception("Arquivo não encontrado: {$this->filename}"); 28 | } 29 | 30 | $this->content = file_get_contents($this->filename); 31 | 32 | $this->codigo_banco = (int) $codigo_banco; 33 | 34 | $linhas = explode("\r\n", $this->content); 35 | if (count($linhas) < 2) { 36 | $linhas = explode("\n", $this->content); 37 | } 38 | $this->header = new HeaderArquivo($this); 39 | $this->trailer = new TrailerArquivo($this); 40 | 41 | $lastLote = null; 42 | 43 | $posLinha = 0; 44 | 45 | foreach ($linhas as $linha) { 46 | if (!trim($linha)) { 47 | continue; 48 | } 49 | 50 | $linhaRetorno = new Linha(); 51 | $linhaRetorno->pos = $posLinha++; 52 | $linhaRetorno->texto = $linha; 53 | 54 | $this->linhas[] = $linhaRetorno; 55 | 56 | $tipo_registro = substr($linha, 7, 1); 57 | if ($tipo_registro == '0') { 58 | // header 59 | $this->header->loadFromString($linha); 60 | $linhaRetorno->linhaCnab = $this->header; 61 | } elseif ($tipo_registro == '1') { 62 | // header do lote 63 | if ($lastLote) { 64 | $this->lotes[] = $lastLote; 65 | } 66 | $lastLote = new Lote($this); 67 | $lastLote->header = new HeaderLote($this); 68 | $lastLote->header->loadFromString($linha); 69 | 70 | $linhaRetorno->linhaCnab = $lastLote->header; 71 | } elseif ($tipo_registro == '2') { 72 | // registros iniciais do lote (opcional) 73 | } elseif ($tipo_registro == '3') { 74 | // registros de detalhe - Segmentos 75 | if ($lastLote) { 76 | $linhaRetorno->linhaCnab = $lastLote->insertSegmento($linha); 77 | } 78 | } elseif ($tipo_registro == '4') { 79 | // registros finais do lote (opcional) 80 | } elseif ($tipo_registro == '5') { 81 | // registro trailer do lote 82 | $lastLote->trailer = new TrailerLote($this); 83 | $lastLote->trailer->loadFromString($linha); 84 | $this->lotes[] = $lastLote; 85 | $linhaRetorno->linhaCnab = $lastLote->trailer; 86 | $lastLote = null; 87 | } elseif ($tipo_registro == '9') { 88 | // trailer do arquivo 89 | $this->trailer->loadFromString($linha); 90 | 91 | $linhaRetorno->linhaCnab = $this->trailer; 92 | } 93 | } 94 | } 95 | 96 | public function listDetalhes() 97 | { 98 | $detalhes = array(); 99 | foreach ($this->lotes as $lote) { 100 | foreach ($lote->listDetalhes() as $detalhe) { 101 | $detalhes[] = $detalhe; 102 | } 103 | } 104 | 105 | return $detalhes; 106 | } 107 | 108 | /** 109 | * Retorna o numero da conta. 110 | * 111 | * @return string 112 | */ 113 | public function getConta() 114 | { 115 | return $this->header->getConta(); 116 | } 117 | 118 | /** 119 | * Retorna o digito de auto conferencia da conta. 120 | * 121 | * @return string 122 | */ 123 | public function getContaDac() 124 | { 125 | return $this->header->getContaDac(); 126 | } 127 | 128 | /** 129 | * Retorna o codigo do banco. 130 | * 131 | * @return string 132 | */ 133 | public function getCodigoBanco() 134 | { 135 | return $this->header->codigo_banco; 136 | } 137 | 138 | /** 139 | * Retorna a data de geração do arquivo. 140 | * 141 | * @return \DateTime 142 | */ 143 | public function getDataGeracao() 144 | { 145 | $data_geracao_str = $this->header->data_geracao; 146 | $format = strlen($data_geracao_str) > 6 ? 'dmY' : 'dmy'; 147 | $format_printf = strlen($data_geracao_str) > 6 ? '%08d' : '%06d'; 148 | 149 | return $data_geracao_str ? \DateTime::createFromFormat($format, sprintf($format_printf, $data_geracao_str)) : false; 150 | } 151 | 152 | /** 153 | * Retorna o objeto DateTime da data crédito do arquivo 154 | * É melhor consultar no Detalhe a data de crédito, a caixa só informa no detalhe 155 | * (Esta função poderá ser removida, pois em alguns banco você só encontra esta data no detalhe). 156 | * 157 | * @return DateTime 158 | */ 159 | public function getDataCredito() 160 | { 161 | $lote = $this->lotes[0]; 162 | $header_lote = $lote->header; 163 | 164 | return $header_lote->data_credito ? \DateTime::createFromFormat('dmY', sprintf('%08d', $header_lote->data_credito)) : false; 165 | } 166 | 167 | public function getCodigoConvenio() 168 | { 169 | return $this->header->getCodigoConvenio(); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/Detalhe.php: -------------------------------------------------------------------------------- 1 | codigo_banco = $arquivo->codigo_banco; 17 | $this->arquivo = $arquivo; 18 | } 19 | 20 | /** 21 | * Retorno se é para dar baixa no boleto. 22 | * 23 | * @return bool 24 | */ 25 | public function isBaixa() 26 | { 27 | $codigo_movimento = $this->segmento_t->codigo_movimento; 28 | 29 | return self::isBaixaStatic($codigo_movimento); 30 | } 31 | 32 | public static function isBaixaStatic($codigo_movimento) 33 | { 34 | $tipo_baixa = array(6, 9, 17, 25); 35 | $codigo_movimento = (int) $codigo_movimento; 36 | if (in_array($codigo_movimento, $tipo_baixa)) { 37 | return true; 38 | } else { 39 | return false; 40 | } 41 | } 42 | 43 | /** 44 | * Retorno se é uma baixa rejeitada. 45 | * 46 | * @return bool 47 | */ 48 | public function isBaixaRejeitada() 49 | { 50 | $tipo_baixa = array(3, 26, 30); 51 | $codigo_movimento = (int) $this->segmento_t->codigo_movimento; 52 | if (in_array($codigo_movimento, $tipo_baixa)) { 53 | return true; 54 | } else { 55 | return false; 56 | } 57 | } 58 | 59 | /** 60 | * Identifica o tipo de detalhe, se por exemplo uma taxa de manutenção. 61 | * 62 | * @return int 63 | */ 64 | public function getCodigo() 65 | { 66 | return (int) $this->segmento_t->codigo_movimento; 67 | } 68 | 69 | /** 70 | * Retorna o valor recebido em conta. 71 | * 72 | * @return float 73 | */ 74 | public function getValorRecebido() 75 | { 76 | return $this->segmento_u->valor_liquido; 77 | } 78 | 79 | /** 80 | * Retorna o valor do título. 81 | * 82 | * @return float 83 | */ 84 | public function getValorTitulo() 85 | { 86 | return $this->segmento_t->valor_titulo; 87 | } 88 | 89 | /** 90 | * Retorna o valor do pago. 91 | * 92 | * @return float 93 | */ 94 | public function getValorPago() 95 | { 96 | return $this->segmento_u->valor_pago; 97 | } 98 | 99 | /** 100 | * Retorna o valor da tarifa. 101 | * 102 | * @return float 103 | */ 104 | public function getValorTarifa() 105 | { 106 | return $this->segmento_t->valor_tarifa; 107 | } 108 | 109 | /** 110 | * Retorna o valor do Imposto sobre operações financeiras. 111 | * 112 | * @return float 113 | */ 114 | public function getValorIOF() 115 | { 116 | return $this->segmento_u->valor_iof; 117 | } 118 | 119 | /** 120 | * Retorna o valor dos descontos concedido (antes da emissão). 121 | * 122 | * @return Double; 123 | */ 124 | public function getValorDesconto() 125 | { 126 | return $this->segmento_u->valor_desconto; 127 | } 128 | 129 | /** 130 | * Retorna o valor dos abatimentos concedidos (depois da emissão). 131 | * 132 | * @return float 133 | */ 134 | public function getValorAbatimento() 135 | { 136 | return $this->segmento_u->valor_abatimento; 137 | } 138 | 139 | /** 140 | * Retorna o valor de outras despesas. 141 | * 142 | * @return float 143 | */ 144 | public function getValorOutrasDespesas() 145 | { 146 | return $this->segmento_u->valor_outras_despesas; 147 | } 148 | 149 | /** 150 | * Retorna o valor de outros creditos. 151 | * 152 | * @return float 153 | */ 154 | public function getValorOutrosCreditos() 155 | { 156 | return $this->segmento_u->valor_outros_creditos; 157 | } 158 | 159 | /** 160 | * Retorna o número do documento do boleto. 161 | * 162 | * @return string 163 | */ 164 | public function getNumeroDocumento() 165 | { 166 | $numero_documento = $this->segmento_t->numero_documento; 167 | if (trim($numero_documento, '0') == '') { 168 | return; 169 | } 170 | 171 | return $numero_documento; 172 | } 173 | 174 | /** 175 | * Retorna o nosso número do boleto. 176 | * 177 | * @return string 178 | */ 179 | public function getNossoNumero() 180 | { 181 | $nossoNumero = $this->segmento_t->nosso_numero; 182 | 183 | if ($this->codigo_banco == 1) { 184 | $nossoNumero = preg_replace( 185 | '/^'.strval($this->arquivo->getCodigoConvenio()).'/', 186 | '', 187 | $nossoNumero 188 | ); 189 | } 190 | 191 | if (in_array($this->codigo_banco, array(\Cnab\Banco::SANTANDER))) { 192 | // retira o dv 193 | $nossoNumero = substr($nossoNumero, 0, -1); 194 | } 195 | 196 | return $nossoNumero; 197 | } 198 | 199 | /** 200 | * Retorna o objeto \DateTime da data de vencimento do boleto. 201 | * 202 | * @return \DateTime 203 | */ 204 | public function getDataVencimento() 205 | { 206 | $data = $this->segmento_t->data_vencimento ? \DateTime::createFromFormat('dmY', sprintf('%08d', $this->segmento_t->data_vencimento)) : false; 207 | if ($data) { 208 | $data->setTime(0, 0, 0); 209 | } 210 | 211 | return $data; 212 | } 213 | 214 | /** 215 | * Retorna a data em que o dinheiro caiu na conta. 216 | * 217 | * @return \DateTime 218 | */ 219 | public function getDataCredito() 220 | { 221 | $data = $this->segmento_u->data_credito ? \DateTime::createFromFormat('dmY', sprintf('%08d', $this->segmento_u->data_credito)) : false; 222 | if ($data) { 223 | $data->setTime(0, 0, 0); 224 | } 225 | 226 | return $data; 227 | } 228 | 229 | /** 230 | * Retorna o valor de juros e mora. 231 | */ 232 | public function getValorMoraMulta() 233 | { 234 | return $this->segmento_u->valor_acrescimos; 235 | } 236 | 237 | /** 238 | * Retorna a data da ocorrencia, o dia do pagamento. 239 | * 240 | * @return \DateTime 241 | */ 242 | public function getDataOcorrencia() 243 | { 244 | $data = $this->segmento_u->data_ocorrencia ? \DateTime::createFromFormat('dmY', sprintf('%08d', $this->segmento_u->data_ocorrencia)) : false; 245 | if ($data) { 246 | $data->setTime(0, 0, 0); 247 | } 248 | 249 | return $data; 250 | } 251 | 252 | /** 253 | * Retorna o número da carteira do boleto. 254 | * 255 | * @return string 256 | */ 257 | public function getCarteira() 258 | { 259 | if ($this->codigo_banco == 104) { 260 | /* 261 | É formado apenas o código da carteira 262 | Código da Carteira 263 | Código adotado pela FEBRABAN, para identificar a característica dos títulos dentro das modalidades de 264 | cobrança existentes no banco. 265 | ‘1’ = Cobrança Simples 266 | ‘3’ = Cobrança Caucionada 267 | ‘4’ = Cobrança Descontada 268 | O Código ‘1’ Cobrança Simples deve ser obrigatoriamente informado nas modalidades Cobrança Simples 269 | e Cobrança Rápida. 270 | */ 271 | return; 272 | } elseif ($this->segmento_t->existField('carteira')) { 273 | return $this->segmento_t->carteira; 274 | } else { 275 | return; 276 | } 277 | } 278 | 279 | /** 280 | * Retorna o número da agencia do boleto. 281 | * 282 | * @return string 283 | */ 284 | public function getAgencia() 285 | { 286 | return $this->segmento_t->agencia_mantenedora; 287 | } 288 | 289 | /** 290 | * Retorna o número da agencia do boleto. 291 | * 292 | * @return string 293 | */ 294 | public function getAgenciaDv() 295 | { 296 | return $this->segmento_t->agencia_dv; 297 | } 298 | 299 | /** 300 | * Retorna a agencia cobradora. 301 | * 302 | * @return string 303 | */ 304 | public function getAgenciaCobradora() 305 | { 306 | return $this->segmento_t->agencia_cobradora; 307 | } 308 | 309 | /** 310 | * Retorna a o dac da agencia cobradora. 311 | * 312 | * @return string 313 | */ 314 | public function getAgenciaCobradoraDac() 315 | { 316 | return $this->segmento_t->agencia_cobradora_dac; 317 | } 318 | 319 | /** 320 | * Retorna o numero sequencial. 321 | * 322 | * @return Integer; 323 | */ 324 | public function getNumeroSequencial() 325 | { 326 | return $this->segmento_t->numero_sequencial_lote; 327 | } 328 | 329 | /** 330 | * Retorna o nome do código. 331 | * 332 | * @return string 333 | */ 334 | public function getCodigoNome() 335 | { 336 | $codigo = (int) $this->getCodigo(); 337 | 338 | $table = array( 339 | 2 => 'Entrada Confirmada', 340 | 3 => 'Entrada Rejeitada', 341 | 4 => 'Transferência de Carteira/Entrada', 342 | 5 => 'Transferência de Carteira/Baixa', 343 | 6 => 'Liquidação', 344 | 9 => 'Baixa', 345 | 12 => 'Confirmação Recebimento Instrução de Abatimento', 346 | 13 => 'Confirmação Recebimento Instrução de Cancelamento Abatimento', 347 | 14 => 'Confirmação Recebimento Instrução Alteração de Vencimento', 348 | 17 => 'Liquidação Após Baixa ou Liquidação Título Não Registrado', 349 | 19 => 'Confirmação Recebimento Instrução de Protesto', 350 | 20 => 'Confirmação Recebimento Instrução de Sustação/Cancelamento de Protesto', 351 | 23 => 'Remessa a Cartório (Aponte em Cartório)', 352 | 24 => 'Retirada de Cartório e Manutenção em Carteira', 353 | 25 => 'Protestado e Baixado (Baixa por Ter Sido Protestado)', 354 | 26 => 'Instrução Rejeitada', 355 | 27 => 'Confirmação do Pedido de Alteração de Outros Dados', 356 | 28 => 'Débito de Tarifas/Custas', 357 | 30 => 'Alteração de Dados Rejeitada', 358 | 36 => 'Confirmação de envio de e-mail/SMS', 359 | 37 => 'Envio de e-mail/SMS rejeitado', 360 | 43 => 'Estorno de Protesto/Sustação', 361 | 44 => 'Estorno de Baixa/Liquidação', 362 | 45 => 'Alteração de dados', 363 | 51 => 'Título DDA reconhecido pelo sacado', 364 | 52 => 'Título DDA não reconhecido pelo sacado', 365 | 53 => 'Título DDA recusado pela CIP', 366 | ); 367 | 368 | if (array_key_exists($codigo, $table)) { 369 | return $table[$codigo]; 370 | } else { 371 | return 'Desconhecido'; 372 | } 373 | } 374 | 375 | /** 376 | * Retorna o código de liquidação, normalmente usado para 377 | * saber onde o cliente efetuou o pagamento. 378 | * 379 | * @return string 380 | */ 381 | public function getCodigoLiquidacao() 382 | { 383 | // @TODO: Resgatar o código de liquidação 384 | return; 385 | } 386 | 387 | /** 388 | * Retorna a descrição do código de liquidação, normalmente usado para 389 | * saber onde o cliente efetuou o pagamento. 390 | * 391 | * @return string 392 | */ 393 | public function getDescricaoLiquidacao() 394 | { 395 | // @TODO: Resgator descrição do código de liquidação 396 | return; 397 | } 398 | 399 | public function dump() 400 | { 401 | $dump = PHP_EOL; 402 | $dump .= '== SEGMENTO T =='; 403 | $dump .= PHP_EOL; 404 | $dump .= $this->segmento_t->dump(); 405 | $dump .= '== SEGMENTO U =='; 406 | $dump .= PHP_EOL; 407 | $dump .= $this->segmento_u->dump(); 408 | 409 | if ($this->segmento_w) { 410 | $dump .= '== SEGMENTO W =='; 411 | $dump .= PHP_EOL; 412 | $dump .= $this->segmento_w->dump(); 413 | } 414 | 415 | return $dump; 416 | } 417 | 418 | public function isDDA() 419 | { 420 | // @TODO: implementar funçao isDDA no Cnab240 421 | } 422 | 423 | public function getAlegacaoPagador() 424 | { 425 | // @TODO: implementar funçao getAlegacaoPagador no Cnab240 426 | } 427 | } 428 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/HeaderArquivo.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'header_arquivo'); 11 | } 12 | 13 | public function getConta() 14 | { 15 | if ($this->existField('conta')) { 16 | return $this->conta; 17 | } else { 18 | return; 19 | } 20 | } 21 | 22 | public function getContaDac() 23 | { 24 | if ($this->existField('conta_dv')) { 25 | return $this->conta_dv; 26 | } else { 27 | return; 28 | } 29 | } 30 | 31 | public function getCodigoConvenio() 32 | { 33 | if ($this->existField('codigo_convenio')) { 34 | return $this->codigo_convenio; 35 | } else { 36 | return; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/HeaderLote.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'header_lote'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/Lote.php: -------------------------------------------------------------------------------- 1 | arquivo = $arquivo; 20 | $this->codigo_banco = $this->arquivo->codigo_banco; 21 | } 22 | 23 | public function insertSegmento($linha) 24 | { 25 | $codigo_segmento = strtoupper(substr($linha, 13, 1)); 26 | $segmento = null; 27 | if ('T' == $codigo_segmento) { 28 | $segmento = new SegmentoT($this->arquivo); 29 | $segmento->loadFromString($linha); 30 | $this->lastDetalhe = new Detalhe($this->arquivo); 31 | $this->detalhes[] = $this->lastDetalhe; 32 | $this->lastDetalhe->segmento_t = $segmento; 33 | } elseif ('U' == $codigo_segmento) { 34 | $segmento = new SegmentoU($this->arquivo); 35 | $segmento->loadFromString($linha); 36 | if ($this->lastDetalhe) { 37 | $this->lastDetalhe->segmento_u = $segmento; 38 | } 39 | } elseif ('W' == $codigo_segmento) { 40 | $segmento = new SegmentoW($this->arquivo); 41 | $segmento->loadFromString($linha); 42 | if ($this->lastDetalhe) { 43 | $this->lastDetalhe->segmento_w = $segmento; 44 | } 45 | } 46 | 47 | return $segmento; 48 | } 49 | 50 | public function listDetalhes() 51 | { 52 | return $this->detalhes; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/SegmentoT.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'retorno/detalhe_segmento_t'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/SegmentoU.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'retorno/detalhe_segmento_u'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/SegmentoW.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'retorno/detalhe_segmento_w'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/TrailerArquivo.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'trailer_arquivo'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab240/TrailerLote.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab240', 'trailer_lote'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab400/Arquivo.php: -------------------------------------------------------------------------------- 1 | filename = $filename; 26 | $this->layoutVersao = $layoutVersao; 27 | 28 | if (!file_exists($this->filename)) { 29 | throw new Exception("Arquivo não encontrado: {$this->filename}"); 30 | } 31 | 32 | $this->content = file_get_contents($this->filename); 33 | 34 | $this->codigo_banco = (int) $codigo_banco; 35 | 36 | $linhas = explode("\r\n", $this->content); 37 | if (count($linhas) < 2) { 38 | $linhas = explode("\n", $this->content); 39 | } 40 | $this->header = new Header($this); 41 | $this->trailer = new Trailer($this); 42 | 43 | $posLinha = 0; 44 | 45 | foreach ($linhas as $linha) { 46 | if (!trim($linha)) { 47 | continue; 48 | } 49 | 50 | $linhaRetorno = new Linha(); 51 | $linhaRetorno->pos = $posLinha++; 52 | $linhaRetorno->texto = $linha; 53 | 54 | $this->linhas[] = $linhaRetorno; 55 | 56 | $tipo_registro = substr($linha, 0, 1); 57 | 58 | if ($tipo_registro == '0' && $linha) { 59 | $this->header->loadFromString($linha); 60 | 61 | $linhaRetorno->linhaCnab = $this->header; 62 | } elseif (in_array((int) $tipo_registro, array(1, 7))) { 63 | $detalhe = new Detalhe($this); 64 | $detalhe->loadFromString($linha); 65 | $this->detalhes[] = $detalhe; 66 | 67 | $linhaRetorno->linhaCnab = $detalhe; 68 | } elseif ($tipo_registro == '9') { 69 | $this->trailer->loadFromString($linha); 70 | $linhaRetorno->linhaCnab = $this->trailer; 71 | } 72 | } 73 | } 74 | 75 | public function listDetalhes() 76 | { 77 | return $this->detalhes; 78 | } 79 | 80 | /** 81 | * Retorna o numero da conta. 82 | * 83 | * @return string 84 | */ 85 | public function getConta() 86 | { 87 | return $this->header->getConta(); 88 | } 89 | 90 | /** 91 | * Retorna o código do cedente / código da empresa / código do convênio (cada banco chama de um nome). 92 | * 93 | * @return string 94 | */ 95 | public function getCodigoCedente() 96 | { 97 | return $this->header->getCodigoCedente(); 98 | } 99 | 100 | /** 101 | * Retorna o digito de auto conferencia da conta. 102 | * 103 | * @return string 104 | */ 105 | public function getContaDac() 106 | { 107 | return $this->header->getContaDac(); 108 | } 109 | 110 | /** 111 | * Retorna o codigo do banco. 112 | * 113 | * @return string 114 | */ 115 | public function getCodigoBanco() 116 | { 117 | return $this->header->codigo_do_banco; 118 | } 119 | 120 | /** 121 | * Retorna a data de geração do arquivo. 122 | * 123 | * @return \DateTime 124 | */ 125 | public function getDataGeracao() 126 | { 127 | $data = $this->header->data_de_geracao ? \DateTime::createFromFormat('dmy', sprintf('%06d', $this->header->data_de_geracao)) : false; 128 | if ($data) { 129 | $data->setTime(0, 0, 0); 130 | } 131 | 132 | return $data; 133 | } 134 | 135 | /** 136 | * Retorna o objeto DateTime da data crédito do arquivo 137 | * É melhor consultar no Detalhe a data de crédito, a caixa só informa no detalhe 138 | * (Esta função poderá ser removida, pois em alguns banco você só encontra esta data no detalhe). 139 | * 140 | * @return DateTime 141 | */ 142 | public function getDataCredito() 143 | { 144 | if ($this->header->existField('data_de_credito')) { 145 | $data = $this->header->data_de_credito ? \DateTime::createFromFormat('dmy', sprintf('%06d', $this->header->data_de_credito)) : false; 146 | if ($data) { 147 | $data->setTime(0, 0, 0); 148 | } 149 | 150 | return $data; 151 | } else { 152 | return; 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab400/Header.php: -------------------------------------------------------------------------------- 1 | _codigo_banco = $arquivo->codigo_banco; 12 | $yamlLoad = new \Cnab\Format\YamlLoad($arquivo->codigo_banco, $arquivo->layoutVersao); 13 | $yamlLoad->load($this, 'cnab400', 'retorno/header_arquivo'); 14 | } 15 | 16 | public function getConta() 17 | { 18 | if ($this->existField('conta')) { 19 | return $this->conta; 20 | } elseif ($this->_codigo_banco == 104) { 21 | $codigo_cedente = sprintf('%016d', $this->codigo_cedente); 22 | 23 | return substr($codigo_cedente, 7, 8); 24 | } 25 | } 26 | 27 | public function getContaDac() 28 | { 29 | if ($this->existField('dac')) { 30 | return $this->dac; 31 | } elseif ($this->_codigo_banco == 104) { 32 | $codigo_cedente = sprintf('%016d', $this->codigo_cedente); 33 | 34 | return substr($codigo_cedente, 15, 1); 35 | } 36 | } 37 | 38 | public function getCodigoCedente() 39 | { 40 | if ($this->existField('codigo_cedente')) { 41 | return $this->codigo_cedente; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/Cnab400/Trailer.php: -------------------------------------------------------------------------------- 1 | codigo_banco, $arquivo->layoutVersao); 10 | $yamlLoad->load($this, 'cnab400', 'retorno/trailer_arquivo'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/CodigoOcorrencia.php: -------------------------------------------------------------------------------- 1 | loadFormat($format, 'retorno/codigo_ocorrencia'); 17 | 18 | $codigo_banco = str_pad($codigo_banco, 3, '0', STR_PAD_LEFT); 19 | 20 | if (array_key_exists($codigo_banco, $array) && array_key_exists($codigo_ocorrencia, $array[$codigo_banco])) { 21 | return $array[$codigo_banco][$codigo_ocorrencia]; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Cnab/Retorno/IArquivo.php: -------------------------------------------------------------------------------- 1 | assertTrue(Banco::existBanco(Banco::ITAU)); 12 | $this->assertTrue(Banco::existBanco(Banco::CEF)); 13 | $this->assertTrue(Banco::existBanco(Banco::SANTANDER)); 14 | $this->assertTrue(Banco::existBanco(Banco::BRADESCO)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/Cnab/Format/LinhaTest.php: -------------------------------------------------------------------------------- 1 | addField('codigo_banco', 1, 3, '9(3)', '000', array()); 13 | $this->assertTrue($linha->existField('codigo_banco')); 14 | $this->assertFalse($linha->existField('codigo_branco')); 15 | $this->assertTrue($linha->validate()); 16 | } 17 | 18 | /** 19 | * @depends testPodeAdicionarCampo 20 | */ 21 | public function testPodeSubstituirCampo() 22 | { 23 | $linha = new Linha(); 24 | $linha->addField('codigo_cedente_dv', 36, 36, '9(1)', '1', array()); 25 | $linha->addField('uso_exclusivo_banco_01', 33, 40, 'X(8)', str_repeat(' ', 8), array()); 26 | $this->assertFalse($linha->existField('codigo_cedente_dv')); 27 | $this->assertTrue($linha->existField('uso_exclusivo_banco_01')); 28 | 29 | $linha = new Linha(); 30 | $linha->addField('codigo_banco', 1, 3, '9(3)', '000', array()); 31 | $linha->addField('numero_lote', 4, 7, '9(4)', '000', array()); 32 | $this->assertTrue($linha->existField('codigo_banco')); 33 | $this->assertTrue($linha->existField('numero_lote')); 34 | 35 | $linha->addField('codigo_banco', 1, 7, '9(7)', '00000000', array()); 36 | $this->assertTrue($linha->existField('codigo_banco')); 37 | $this->assertTrue($linha->validate()); 38 | 39 | $linha->addField('codigo_e_lote', 1, 7, '9(7)', '2', array()); 40 | $this->assertTrue($linha->existField('codigo_e_lote')); 41 | $this->assertFalse($linha->existField('codigo_banco')); 42 | $this->assertFalse($linha->existField('numero_lote')); 43 | $this->assertTrue($linha->validate()); 44 | 45 | return $linha; 46 | } 47 | 48 | /** 49 | * @depends testPodeSubstituirCampo 50 | */ 51 | public function testPodeCodificarLinha($linha) 52 | { 53 | $linha->addField('teste', 8, 12, 'X(5)', 'teste', array()); 54 | 55 | $encoded = $linha->getEncoded(); 56 | $this->assertEquals(12, strlen($encoded)); 57 | $this->assertEquals('0000002teste', $encoded); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/Cnab/Format/PictureTest.php: -------------------------------------------------------------------------------- 1 | assertEquals(200.00, Picture::decode('20000', '9(3)V9(2)', array())); 13 | $this->assertEquals(200.05, Picture::decode('20005', '9(3)V9(2)', array())); 14 | $this->assertEquals(2.5, Picture::decode('00250', '9(3)V9(2)', array())); 15 | $this->assertEquals(3.33, Picture::decode('0333', '9(2)V9(2)', array())); 16 | 17 | // integer number 18 | $this->assertEquals(200, Picture::decode('00200', '9(5)', array())); 19 | $this->assertEquals(3, Picture::decode('3', '9(1)', array())); 20 | $this->assertEquals(70.46, Picture::decode('07046', '9(3)V9(2)', array())); 21 | 22 | // big integer number 23 | $this->assertEquals('123456789123456', Picture::decode('000123456789123456', '9(15)', array())); 24 | 25 | // too big integer number 26 | $this->assertEquals('900000000048957', Picture::decode('900000000048957', '9(15)', array())); 27 | 28 | // string text 29 | $this->assertEquals(' Abc', Picture::decode(' Abc', 'X(5)', array())); 30 | $this->assertEquals('Abc', Picture::decode('Abc ', 'X(5)', array())); 31 | } 32 | 33 | public function testEncode() 34 | { 35 | // float number 36 | $this->assertEquals('20000', Picture::encode(200.00, '9(3)V9(2)', array())); 37 | $this->assertEquals('20005', Picture::encode(200.05, '9(3)V9(2)', array())); 38 | $this->assertEquals('20050', Picture::encode(200.50, '9(3)V9(2)', array())); 39 | $this->assertEquals('00250', Picture::encode(2.5, '9(3)V9(2)', array())); 40 | $this->assertEquals('00205', Picture::encode(2.05, '9(3)V9(2)', array())); 41 | $this->assertEquals('07046', Picture::encode(70.45999999999999, '9(3)V9(2)', array())); 42 | $this->assertEquals('07045', Picture::encode(70.45111111111111, '9(3)V9(2)', array())); 43 | $this->assertEquals('070451', Picture::encode(70.45111111111111, '9(3)V9(3)', array())); 44 | 45 | $linha = new \Cnab\Format\Linha(); 46 | $field = new \Cnab\Format\Field($linha, 'valor_titulo', '9(3)V9(2)', 0, 4, array()); 47 | $field->set(70.45999999999999); 48 | $this->assertEquals('07046', $field->getEncoded()); 49 | 50 | // integer number 51 | $this->assertEquals('0200', Picture::encode(200, '9(4)', array())); 52 | $this->assertEquals('4', Picture::encode(4, '9(1)', array())); 53 | 54 | // big integer number 55 | $this->assertEquals('900000000048957', Picture::encode('900000000048957', '9(15)', array())); 56 | 57 | // string text 58 | $this->assertEquals('Abc ', Picture::encode('Abc', 'X(5)', array())); 59 | $this->assertEquals(' 123 ', Picture::encode(' 123', 'X(5)', array())); 60 | 61 | // encode date 62 | $data = new \DateTime('2003-02-01 00:00:00'); 63 | $this->assertEquals('01022003', Picture::encode($data, '9(8)', array('date_format' => '%d%m%Y'))); 64 | 65 | $data = new \DateTime('2009-08-07 01:02:03'); 66 | $this->assertEquals('010203', Picture::encode($data, '9(8)', array('date_format' => '%H%M%S'))); 67 | $this->assertEquals('030201', Picture::encode($data, '9(8)', array('date_format' => '%S%M%H'))); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/Cnab/Format/YamlLoadTest.php: -------------------------------------------------------------------------------- 1 | array( 22 | 'pos' => array(1, 3), 23 | ), 24 | 'tipo_registro' => array( 25 | 'pos' => array(1, 4), 26 | ), 27 | ); 28 | 29 | $yamlLoad->validateCollision($fields); 30 | } 31 | 32 | public function testNaoEmiteExceptionEmCamposSemColisao() 33 | { 34 | $yamlLoad = new YamlLoad(0); 35 | 36 | $fields1 = array( 37 | 'codigo_banco' => array( 38 | 'pos' => array(1, 3), 39 | ), 40 | 'tipo_registro' => array( 41 | 'pos' => array(4, 4), 42 | ), 43 | ); 44 | 45 | $fields2 = array( 46 | 'codigo_banco' => array( 47 | 'pos' => array(1, 3), 48 | ), 49 | ); 50 | 51 | $this->assertTrue($yamlLoad->validateCollision($fields1)); 52 | $this->assertTrue($yamlLoad->validateCollision($fields2)); 53 | } 54 | 55 | /** 56 | * @expectedException DomainException 57 | */ 58 | public function testEmiteExceptionEmArrayMalformado() 59 | { 60 | $array = array( 61 | 'generic' => array( 62 | 'codigo_banco' => array( 63 | 'pos' => array(1, 3), 64 | 'picture' => '', 65 | ), 66 | 'tipo_registro' => array( 67 | 'pos' => array(4, 4), 68 | 'picture' => '', 69 | ), 70 | ), 71 | '033' => array( 72 | 'nome_empresa' => array( 73 | 'pos' => array(40, 80), 74 | 'picture' => '', 75 | ), 76 | 'numero_inscricao' => array( 77 | 'pos' => array(79, 80), 78 | 'picture' => '', 79 | ), 80 | ), 81 | ); 82 | 83 | $yamlLoad = new YamlLoad(0); 84 | $yamlLoad->validateArray($array); 85 | } 86 | 87 | public function testNaoEmiteExceptionEmArrayValido() 88 | { 89 | $array = array( 90 | 'generic' => array( 91 | 'codigo_banco' => array( 92 | 'pos' => array(1, 3), 93 | 'picture' => '', 94 | ), 95 | 'tipo_registro' => array( 96 | 'pos' => array(4, 4), 97 | 'picture' => '', 98 | ), 99 | ), 100 | '033' => array( 101 | 'nome_empresa' => array( 102 | 'pos' => array(40, 80), 103 | 'picture' => '', 104 | ), 105 | 'numero_inscricao' => array( 106 | 'pos' => array(81, 81), 107 | 'picture' => '', 108 | ), 109 | ), 110 | ); 111 | 112 | $yamlLoad = new YamlLoad(0); 113 | $this->assertTrue($yamlLoad->validateArray($array)); 114 | } 115 | 116 | public function testBuscaFormatoGenericoEEspecifico() 117 | { 118 | $yamlLoad = $this->getMockBuilder('\Cnab\Format\YamlLoad') 119 | ->setMethods(array('loadYaml')) 120 | ->setConstructorArgs(array(33)) 121 | ->getMock(); 122 | 123 | $testFormat = array( 124 | 'codigo_banco' => array( 125 | 'pos' => array(1, 3), 126 | 'picture' => '9(3)', 127 | ), 128 | ); 129 | 130 | $yamlLoad->expects($this->at(0)) 131 | ->method('loadYaml') 132 | ->with( 133 | $this->equalTo($yamlLoad->formatPath.'/cnab240/generic/header_lote.yml') 134 | ) 135 | ->will($this->returnValue($testFormat)); 136 | 137 | $yamlLoad->expects($this->at(1)) 138 | ->method('loadYaml') 139 | ->with( 140 | $this->equalTo($yamlLoad->formatPath.'/cnab240/033/header_lote.yml') 141 | ) 142 | ->will($this->returnValue($testFormat)); 143 | 144 | $linha = new Linha(); 145 | $yamlLoad->load($linha, 'cnab240', 'header_lote'); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /tests/Cnab/Remessa/Cnab240/BancoDoBrasilTest.php: -------------------------------------------------------------------------------- 1 | markTestIncomplete('A versão do layout foi alterada de 020 para 030, porém não ainda está em beta e não foram feitos testes para a nova versão'); 10 | 11 | $codigoBanco = \Cnab\Banco::BANCO_DO_BRASIL; 12 | $cnabFactory = new \Cnab\Factory(); 13 | $arquivo = $cnabFactory->createRemessa($codigoBanco, 'cnab240'); 14 | $arquivo->configure(array( 15 | 'data_geracao' => new \DateTime('2015-02-01 01:02:03'), 16 | 'data_gravacao' => new \DateTime('2015-02-01'), 17 | 'nome_fantasia' => 'Nome Fantasia da sua empresa', 18 | 'razao_social' => 'Razão social da sua empresa', 19 | 'cnpj' => '11222333444455', 20 | 'banco' => $codigoBanco, //código do banco 21 | 'logradouro' => 'Logradouro da Sua empresa', 22 | 'numero' => 'Número do endereço', 23 | 'bairro' => 'Bairro da sua empresa', 24 | 'cidade' => 'Cidade da sua empresa', 25 | 'uf' => 'SP', 26 | 'cep' => '00000111', 27 | 'conta' => '123456', 28 | 'conta_dv' => '5', 29 | 'operacao' => '012', 30 | 'agencia' => '1234', 31 | 'agencia_dv' => '3', 32 | 'codigo_convenio' => '123123', 33 | 'codigo_carteira' => '11', // número da carteira 34 | 'variacao_carteira' => '345', 35 | 'numero_sequencial_arquivo' => 1, 36 | )); 37 | 38 | // você pode adicionar vários boletos em uma remessa 39 | $arquivo->insertDetalhe(array( 40 | 'codigo_ocorrencia' => 1, // 1 = Entrada de título, futuramente poderemos ter uma constante 41 | 'nosso_numero' => '12345', 42 | 'numero_documento' => '12345678', 43 | 'carteira' => '11', 44 | 'codigo_carteira' => \Cnab\CodigoCarteira::COBRANCA_SIMPLES, 45 | 'especie' => \Cnab\Especie::BB_DUPLICATA_MERCANTIL, // Você pode consultar as especies Cnab\Especie::CEF_OUTROS, futuramente poderemos ter uma tabela na documentação 46 | 'aceite' => 'N', // "S" ou "N" 47 | 'registrado' => false, 48 | 'valor' => 100.39, // Valor do boleto 49 | 'instrucao1' => '', // 1 = Protestar com (Prazo) dias, 2 = Devolver após (Prazo) dias, futuramente poderemos ter uma constante 50 | 'instrucao2' => '', // preenchido com zeros 51 | 'sacado_razao_social' => 'Nome do cliente', // O Sacado é o cliente, preste atenção nos campos abaixo 52 | 'sacado_tipo' => 'cnpj', //campo fixo, escreva 'cpf' (sim as letras cpf) se for pessoa fisica, cnpj se for pessoa juridica 53 | 'sacado_cnpj' => '21.222.333.4444-55', 54 | 'sacado_logradouro' => 'Logradouro do cliente', 55 | 'sacado_bairro' => 'Bairro do cliente', 56 | 'sacado_cep' => '00000-111', 57 | 'sacado_cidade' => 'Cidade do cliente', 58 | 'sacado_uf' => 'BA', 59 | 'data_vencimento' => new \DateTime('2015-02-03'), 60 | 'data_cadastro' => new \DateTime('2015-01-14'), 61 | 'codigo_juros_mora' => 2, //‘1’ = Valor por Dia, ‘2’ = Taxa Mensal, ‘3’ = Isento 62 | 'juros_de_um_dia' => 0.10, // Valor de 1 dia ou taxa do juros de 1 mês 63 | 'data_desconto' => new \DateTime('2015-02-09'), 64 | 'valor_desconto' => 10.0, // Valor do desconto 65 | 'prazo' => 10, // prazo de dias para o cliente pagar após o vencimento 66 | 'taxa_de_permanencia' => '0', //00 = Acata Comissão por Dia (recomendável), 51 Acata Condições de Cadastramento na CAIXA 67 | 'mensagem' => 'Descrição do boleto', 68 | 'data_multa' => new \DateTime('2015-02-07'), // data da multa 69 | 'valor_multa' => 11.2, // valor da multa 70 | 'baixar_apos_dias' => 30, 71 | 'dias_iniciar_contagem_juros' => 1, 72 | )); 73 | 74 | $texto = $arquivo->getText(); 75 | $lines = explode("\r\n", trim($texto, "\r\n")); 76 | 77 | $this->assertEquals(7, count($lines)); 78 | 79 | $headerArquivoText = $lines[0]; 80 | $headerLoteText = $lines[1]; 81 | $segmentoPText = $lines[2]; 82 | $segmentoQText = $lines[3]; 83 | $segmentoRText = $lines[4]; 84 | $trailerLoteText = $lines[5]; 85 | $trailerArquivoText = $lines[6]; 86 | 87 | $asserts = array( 88 | 'headerArquivo' => array( 89 | '1:3' => '001', // codigo_banco 90 | '4:7' => '0000', // lote_servico 91 | '8:8' => '0', // tipo_registro 92 | '9:17' => ' ', // uso_exclusivo_febraban_01 93 | '18:18' => '2', // codigo_inscricao 94 | '19:32' => '11222333444455', // numero_inscricao 95 | '33:41' => '000123123', // codigo convenio 96 | '42:45' => '0014', // Cobrança Cedende BB: Informar 0014 para cobrança cedente 97 | '46:47' => '11', // Carteira 98 | '48:50' => '345', // Variação carteira 99 | '51:52' => ' ', // uso reservado bb 100 | '53:57' => '01234', // agencia 101 | '58:58' => '3', // agencia_dv 102 | '59:70' => '000000123456', // conta 103 | '71:71' => '5', // conta dv 104 | '72:72' => ' ', // campo não tratado pelo bb 105 | '73:102' => 'Nome Fantasia da sua empresa ', // nome_empresa 106 | '103:132' => 'BANCO DO BRASIL S.A. ', // nome_banco 107 | '133:142' => ' ', // uso_exclusivo_febraban_02 108 | '143:143' => '1', // codigo_remessa_retorno 109 | '144:151' => '01022015', // data_geracao 110 | '152:157' => '010203', // hora_geracao 111 | '158:163' => '000001', // numero_sequencial_arquivo 112 | '164:166' => '030', // versao_layout_arquivo 113 | '167:171' => '00000', // densidade_gravacao_arquivo 114 | '172:191' => ' ', // Para Uso Reservado do Banco 115 | '192:211' => 'REMESSA-PRODUCAO ', // Para Uso Reservado da Empresa 116 | '212:225' => ' ', // Uso Exclusivo FEBRABAN / CNAB 117 | '226:240' => '0000000000000000', // Uso Exclusivo FEBRABAN / CNAB 118 | ), 119 | 'headerLote' => array( 120 | '1:3' => '001', // codigo_banco 121 | '4:7' => '0001', // lote_servico 122 | '8:8' => '1', // tipo_registro 123 | '9:9' => 'R', // tipo_operacao 124 | '10:11' => '01', // tipo_servico 125 | '12:13' => '00', // Uso Exclusivo FEBRABAN/CNAB 126 | '14:16' => '030', // versao_layout_lote 127 | '17:17' => ' ', // uso_exclusivo_febraban_01 128 | '18:18' => '2', // codigo_inscricao 129 | '19:33' => '011222333444455', // numero_inscricao 130 | '34:42' => '000123123', // codigo_convenio 131 | '43:46' => '0014', // Cobrança cedente, Informar 0014 para cobrança 132 | '47:48' => '11', // carteira 133 | '49:51' => '345', // variaçã carteira 134 | '52:53' => ' ', // Use TS para testes 135 | '54:58' => '01234', // agencia 136 | '59:59' => '3', // agencia_dv 137 | '60:71' => '000000123456', // conta 138 | '72:72' => '5', // conta dv 139 | '73:73' => ' ', // uso_exclusivo_banco_02 140 | '74:103' => 'Nome Fantasia da sua empresa ', // nome_empresa 141 | '104:143' => ' ', // mensagem_1 142 | '144:183' => ' ', // mensagem_2 143 | '184:191' => '00000001', // numero_sequencial_arquivo 144 | '192:199' => '01022015', // data_geracao 145 | '200:207' => '00000000', // data_credito 146 | '208:240' => ' ', // uso_exclusivo_febraban_02 147 | ), 148 | 'segmentoP' => array( 149 | '1:3' => '001', // codigo_banco 150 | '4:7' => '0001', // lote_servico 151 | '8:8' => '3', // tipo_registro 152 | '9:13' => '00001', // numero_sequencial_lote 153 | '14:14' => 'P', // codigo_segmento 154 | '15:15' => ' ', // uso_exclusivo_febraban_01 155 | '16:17' => '01', // codigo_ocorrencia 156 | '18:22' => '01234', // agencia 157 | '23:23' => '3', // agencia_dv 158 | '24:35' => '000000123456', // número da conta 159 | '36:36' => '5', // conta dv 160 | '37:37' => ' ', // Dígito Verificador da Ag/Conta (Não usado pelo BB) 161 | '38:57' => '123123123459 ', // nosso_numero 162 | '58:58' => '1', // codigo_carteira 163 | '59:59' => '2', // forma_cadastramento 164 | '60:60' => '2', // tipo_documento 165 | '61:61' => '2', // identificacao_emissao 166 | '62:62' => '2', // identificacao_distribuicao 167 | '63:77' => '12345678 ', // numero_documento 168 | '78:85' => '03022015', // vencimento 169 | '86:100' => '000000000010039', // valor_titulo 170 | '101:105' => '00000', // agencia_cobradora 171 | '106:106' => '0', // agencia_cobradora_dv 172 | '107:108' => '02', // especie 173 | '109:109' => 'N', // aceite 174 | '110:117' => '14012015', // data_emissao 175 | '118:118' => '1', // codigo_juros_mora 176 | '119:126' => '04022015', // data_juros_mora 177 | '127:141' => '000000000000010', // valor_juros_mora 178 | '142:142' => '1', // codigo_desconto_1 179 | '143:150' => '09022015', // data_desconto_1 180 | '151:165' => '000000000001000', // valor_desconto_1 181 | '166:180' => '000000000000000', // valor_iof 182 | '181:195' => '000000000000000', // valor_abatimento 183 | '196:220' => '12345678 ', // uso_empresa 184 | '221:221' => '3', // codigo_protesto 185 | '222:223' => '00', // prazo_protesto 186 | '224:224' => '0', // codigo_baixa 187 | '225:227' => '000', // prazo_baixa 188 | '228:229' => '09', // codigo_moeda 189 | '230:239' => '0000000000', // uso_exclusivo_banco_03 190 | '240:240' => ' ', // uso_exclusivo_febraban_02 191 | ), 192 | 'segmentoQ' => array( 193 | '1:3' => '001', // codigo_banco 194 | '4:7' => '0001', // lote_servico 195 | '8:8' => '3', // tipo_registro 196 | '9:13' => '00002', // numero_sequencial_lote 197 | '14:14' => 'Q', // codigo_segmento 198 | '15:15' => ' ', // uso_exclusivo_febraban_01 199 | '16:17' => '01', // codigo_ocorrencia 200 | '18:18' => '2', // sacado_codigo_inscricao 201 | '19:33' => '021222333444455', // sacado_numero_inscricao 202 | '34:73' => 'NOME DO CLIENTE ', // nome 203 | '74:113' => 'LOGRADOURO DO CLIENTE ', // logradouro 204 | '114:128' => 'BAIRRO DO CLIEN', // bairro 205 | '129:136' => '00000111', // cep 206 | '137:151' => 'CIDADE DO CLIEN', // cidade 207 | '152:153' => 'BA', // estado 208 | '154:154' => '2', // sacador_codigo_inscricao 209 | '155:169' => '011222333444455', // sacador_numero_inscricao 210 | '170:209' => 'Nome Fantasia da sua empresa ', // sacador_nome 211 | '210:212' => ' ', // uso_exclusivo_febraban_02 212 | '213:232' => ' ', // uso_exclusivo_febraban_03 213 | '233:240' => ' ', // uso_exclusivo_febraban_04 214 | ), 215 | 'segmentoR' => array( 216 | '1:3' => '001', // codigo_banco 217 | '4:7' => '0001', // lote_servico 218 | '8:8' => '3', // tipo_registro 219 | '9:13' => '00003', // numero_sequencial_lote 220 | '14:14' => 'R', // codigo_segmento 221 | '15:15' => ' ', // uso_exclusivo_febraban_01 222 | '16:17' => '01', // codigo_ocorrencia 223 | 224 | // campos não tratado pelo banco do brasil 225 | '18:65' => ' ', // uso_exclusivo_febraban_02 226 | 227 | '66:66' => '1', // codigo_multa 228 | '67:74' => '07022015', // data_multa 229 | '75:89' => '000000000001120', // valor_multa 230 | '90:99' => ' ', // informacao_sacado 231 | '100:139' => ' ', // mensagem_3 232 | '140:179' => ' ', // mensagem_4 233 | '180:240' => ' ', // uso_exclusivo_febraban_03 234 | ), 235 | 'trailerLote' => array( 236 | '1:3' => '001', // codigo_banco 237 | '4:7' => '0001', // lote_servico 238 | '8:8' => '5', // tipo_registro 239 | '18:23' => '000005', // qtde_registro_lote 240 | '24:240' => str_repeat(' ', 217), // uso_exclusivo_febraban_02 241 | ), 242 | 'trailerArquivo' => array( 243 | '1:3' => '001', // codigo_banco 244 | '4:7' => '9999', // lote_servico 245 | '8:8' => '9', // tipo_registro 246 | '9:17' => ' ', // uso_exclusivo_febraban01 247 | '18:23' => '000001', // qtde_lotes 248 | '24:29' => '000007', // qtde_registros 249 | '30:35' => ' ', // uso_exclusivo_febraban02 250 | '36:240' => ' ', // uso_exclusivo_febraban_03 251 | ), 252 | ); 253 | 254 | foreach ($asserts as $tipo => $campos) { 255 | $vname = "{$tipo}Text"; 256 | foreach ($campos as $pos => $value) { 257 | $aux = explode(':', $pos); 258 | $start = $aux[0] - 1; 259 | $end = ($aux[1] - $aux[0]) + 1; 260 | $this->assertEquals($value, substr($$vname, $start, $end), "[ ] Campo $pos do $tipo"); 261 | } 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /tests/Cnab/Remessa/Cnab240/CaixaTest.php: -------------------------------------------------------------------------------- 1 | createRemessa($codigoBanco, 'cnab240', 'sigcb'); 12 | $arquivo->configure(array( 13 | 'data_geracao' => new \DateTime('2015-02-01 01:02:03'), 14 | 'data_gravacao' => new \DateTime('2015-02-01'), 15 | 'nome_fantasia' => 'Nome Fantasia da sua empresa', 16 | 'razao_social' => 'Razão social da sua empresa', 17 | 'cnpj' => '11222333444455', 18 | 'banco' => $codigoBanco, //código do banco 19 | 'logradouro' => 'Logradouro da Sua empresa', 20 | 'numero' => 'Número do endereço', 21 | 'bairro' => 'Bairro da sua empresa', 22 | 'cidade' => 'Cidade da sua empresa', 23 | 'uf' => 'SP', 24 | 'cep' => '00000111', 25 | 'conta' => '123456', 26 | 'operacao' => '012', 27 | 'agencia' => '1234', 28 | 'agencia_dv' => '3', 29 | 'codigo_cedente' => '123123', 30 | 'numero_sequencial_arquivo' => 1, 31 | )); 32 | 33 | // você pode adicionar vários boletos em uma remessa 34 | $arquivo->insertDetalhe(array( 35 | 'codigo_ocorrencia' => 1, // 1 = Entrada de título, futuramente poderemos ter uma constante 36 | 'nosso_numero' => '12345679', 37 | 'numero_documento' => '12345678', 38 | 'carteira' => '111', 39 | 'especie' => \Cnab\Especie::CNAB240_OUTROS, // Você pode consultar as especies Cnab\Especie::CEF_OUTROS, futuramente poderemos ter uma tabela na documentação 40 | 'aceite' => 'N', // "S" ou "N" 41 | 'registrado' => false, 42 | 'modalidade_carteira' => '21', 43 | 'valor' => 100.39, // Valor do boleto 44 | 'instrucao1' => '', // 1 = Protestar com (Prazo) dias, 2 = Devolver após (Prazo) dias, futuramente poderemos ter uma constante 45 | 'instrucao2' => '', // preenchido com zeros 46 | 'sacado_razao_social' => 'Nome do cliente', // O Sacado é o cliente, preste atenção nos campos abaixo 47 | 'sacado_tipo' => 'cnpj', //campo fixo, escreva 'cpf' (sim as letras cpf) se for pessoa fisica, cnpj se for pessoa juridica 48 | 'sacado_cnpj' => '21.222.333.4444-55', 49 | 'sacado_logradouro' => 'Logradouro do cliente', 50 | 'sacado_bairro' => 'Bairro do cliente', 51 | 'sacado_cep' => '00000-111', 52 | 'sacado_cidade' => 'Cidade do cliente', 53 | 'sacado_uf' => 'BA', 54 | 'data_vencimento' => new \DateTime('2015-02-03'), 55 | 'data_cadastro' => new \DateTime('2015-01-14'), 56 | 'juros_de_um_dia' => 0.10, // Valor do juros de 1 dia' 57 | 'data_desconto' => new \DateTime('2015-02-09'), 58 | 'valor_desconto' => 10.0, // Valor do desconto 59 | 'prazo' => 10, // prazo de dias para o cliente pagar após o vencimento 60 | 'taxa_de_permanencia' => '0', //00 = Acata Comissão por Dia (recomendável), 51 Acata Condições de Cadastramento na CAIXA 61 | 'mensagem' => 'Descrição do boleto', 62 | 'data_multa' => new \DateTime('2015-02-07'), // data da multa 63 | 'valor_multa' => 11.2, // valor da multa 64 | 'baixar_apos_dias' => 30, 65 | 'dias_iniciar_contagem_juros' => 1, 66 | )); 67 | 68 | $texto = $arquivo->getText(); 69 | $lines = explode("\r\n", trim($texto, "\r\n")); 70 | 71 | $this->assertEquals(7, count($lines)); 72 | 73 | $headerArquivoText = $lines[0]; 74 | $headerLoteText = $lines[1]; 75 | $segmentoPText = $lines[2]; 76 | $segmentoQText = $lines[3]; 77 | $segmentoRText = $lines[4]; 78 | $trailerLoteText = $lines[5]; 79 | $trailerArquivoText = $lines[6]; 80 | 81 | $asserts = array( 82 | 'headerArquivo' => array( 83 | '1:3' => '104', // codigo_banco 84 | '4:7' => '0000', // lote_servico 85 | '8:8' => '0', // tipo_registro 86 | '9:17' => ' ', // uso_exclusivo_febraban_01 87 | '18:18' => '2', // codigo_inscricao 88 | '19:32' => '11222333444455', // numero_inscricao 89 | '33:52' => '00000000000000000000', // uso exclusivo caixa 90 | '53:57' => '01234', // agencia 91 | '58:58' => '3', // agencia_dv 92 | '59:64' => '123123', // codigo_cedente 93 | '65:71' => '0000000', // uso_exclusivo_caixa_02 94 | '72:72' => '0', // uso_exclusivo_caixa_03 95 | '73:102' => 'Nome Fantasia da sua empresa ', // nome_empresa 96 | '103:132' => 'CAIXA ECONOMICA FEDERAL ', // nome_banco 97 | '133:142' => ' ', // uso_exclusivo_febraban_02 98 | '143:143' => '1', // codigo_remessa_retorno 99 | '144:151' => '01022015', // data_geracao 100 | '152:157' => '010203', // hora_geracao 101 | '158:163' => '000001', // numero_sequencial_arquivo 102 | '164:166' => '050', // versao_layout_arquivo 103 | '167:171' => '00000', // densidade_gravacao_arquivo 104 | '172:191' => ' ', // uso_reservado_banco 105 | '192:211' => 'REMESSA-PRODUCAO ', // uso_reservado_empresa 106 | '212:215' => ' ', // versao_aplicativo_caixa 107 | '216:240' => ' ', // uso_exclusivo_febraban_03 108 | ), 109 | 'headerLote' => array( 110 | '1:3' => '104', // codigo_banco 111 | '4:7' => '0001', // lote_servico 112 | '8:8' => '1', // tipo_registro 113 | '9:9' => 'R', // tipo_operacao 114 | '10:11' => '02', // tipo_servico 115 | '12:13' => '00', // forma_lancamento 116 | '14:16' => '030', // versao_layout_lote 117 | '17:17' => ' ', // uso_exclusivo_febraban_01 118 | '18:18' => '2', // codigo_inscricao 119 | '19:33' => '011222333444455', // numero_inscricao 120 | '34:39' => '123123', // codigo_convenio 121 | '40:53' => '00000000000000', // uso_exclusivo_banco 122 | '54:58' => '01234', // agencia 123 | '59:59' => '3', // agencia_dv 124 | '60:65' => '123123', // codigo_cedente 125 | '66:72' => '0000000', // codigo_modelo 126 | '73:73' => '0', // uso_exclusivo_banco_02 127 | '74:103' => 'Nome Fantasia da sua empresa ', // nome_empresa 128 | '104:143' => ' ', // mensagem_1 129 | '144:183' => ' ', // mensagem_2 130 | '184:191' => '00000001', // numero_sequencial_arquivo 131 | '192:199' => '01022015', // data_geracao 132 | '200:207' => '00000000', // data_credito 133 | '208:240' => ' ', // uso_exclusivo_febraban_02 134 | ), 135 | 'segmentoP' => array( 136 | '1:3' => '104', // codigo_banco 137 | '4:7' => '0001', // lote_servico 138 | '8:8' => '3', // tipo_registro 139 | '9:13' => '00001', // numero_sequencial_lote 140 | '14:14' => 'P', // codigo_segmento 141 | '15:15' => ' ', // uso_exclusivo_febraban_01 142 | '16:17' => '01', // codigo_ocorrencia 143 | '18:22' => '01234', // agencia 144 | '23:23' => '3', // agencia_dv 145 | '24:29' => '123123', // codigo_cedente 146 | '30:37' => '00000000', // uso_exclusivo_caixa_01 147 | '38:40' => '000', // uso_exclusivo_caixa_02 148 | '41:42' => '21', // modalidade_carteira 149 | '43:57' => '000000012345679', // nosso_numero 150 | '58:58' => '1', // codigo_carteira 151 | '59:59' => '2', // forma_cadastramento 152 | '60:60' => '2', // tipo_documento 153 | '61:61' => '2', // identificacao_emissao 154 | '62:62' => '2', // identificacao_distribuicao 155 | '63:73' => '12345678 ', // numero_documento 156 | '74:77' => ' ', // uso_exclusivo_banco_02 157 | '78:85' => '03022015', // vencimento 158 | '86:100' => '000000000010039', // valor_titulo 159 | '101:105' => '00000', // agencia_cobradora 160 | '106:106' => '0', // agencia_cobradora_dv 161 | '107:108' => '99', // especie 162 | '109:109' => 'N', // aceite 163 | '110:117' => '14012015', // data_emissao 164 | '118:118' => '1', // codigo_juros_mora 165 | '119:126' => '04022015', // data_juros_mora 166 | '127:141' => '000000000000010', // valor_juros_mora 167 | '142:142' => '1', // codigo_desconto_1 168 | '143:150' => '09022015', // data_desconto_1 169 | '151:165' => '000000000001000', // valor_desconto_1 170 | '166:180' => '000000000000000', // valor_iof 171 | '181:195' => '000000000000000', // valor_abatimento 172 | '196:220' => '12345678 ', // uso_empresa 173 | '221:221' => '3', // codigo_protesto 174 | '222:223' => '00', // prazo_protesto 175 | '224:224' => '1', // codigo_baixa 176 | '225:227' => '030', // prazo_baixa 177 | '228:229' => '09', // codigo_moeda 178 | '230:239' => '0000000000', // uso_exclusivo_banco_03 179 | '240:240' => ' ', // uso_exclusivo_febraban_02 180 | ), 181 | 'segmentoQ' => array( 182 | '1:3' => '104', // codigo_banco 183 | '4:7' => '0001', // lote_servico 184 | '8:8' => '3', // tipo_registro 185 | '9:13' => '00002', // numero_sequencial_lote 186 | '14:14' => 'Q', // codigo_segmento 187 | '15:15' => ' ', // uso_exclusivo_febraban_01 188 | '16:17' => '01', // codigo_ocorrencia 189 | '18:18' => '2', // sacado_codigo_inscricao 190 | '19:33' => '021222333444455', // sacado_numero_inscricao 191 | '34:73' => 'NOME DO CLIENTE ', // nome 192 | '74:113' => 'LOGRADOURO DO CLIENTE ', // logradouro 193 | '114:128' => 'BAIRRO DO CLIEN', // bairro 194 | '129:136' => '00000111', // cep 195 | '137:151' => 'CIDADE DO CLIEN', // cidade 196 | '152:153' => 'BA', // estado 197 | '154:154' => '2', // sacador_codigo_inscricao 198 | '155:169' => '011222333444455', // sacador_numero_inscricao 199 | '170:209' => 'Nome Fantasia da sua empresa ', // sacador_nome 200 | '210:212' => ' ', // uso_exclusivo_febraban_02 201 | '213:232' => ' ', // uso_exclusivo_febraban_03 202 | '233:240' => ' ', // uso_exclusivo_febraban_04 203 | ), 204 | 'segmentoR' => array( 205 | '1:3' => '104', // codigo_banco 206 | '4:7' => '0001', // lote_servico 207 | '8:8' => '3', // tipo_registro 208 | '9:13' => '00003', // numero_sequencial_lote 209 | '14:14' => 'R', // codigo_segmento 210 | '15:15' => ' ', // uso_exclusivo_febraban_01 211 | '16:17' => '01', // codigo_ocorrencia 212 | '18:65' => '000000000000000000000000000000000000000000000000', // uso_exclusivo_febraban_02 213 | '66:66' => '1', // codigo_multa 214 | '67:74' => '07022015', // data_multa 215 | '75:89' => '000000000001120', // valor_multa 216 | '90:99' => ' ', // informacao_sacado 217 | '100:139' => ' ', // mensagem_3 218 | '140:179' => ' ', // mensagem_4 219 | '180:240' => ' ', // uso_exclusivo_febraban_03 220 | ), 221 | 'trailerLote' => array( 222 | '1:3' => '104', // codigo_banco 223 | '4:7' => '0001', // lote_servico 224 | '8:8' => '5', // tipo_registro 225 | '18:23' => '000005', // qtde_registro_lote 226 | '24:29' => '000001', // qtde_titulo_cobranca_simples 227 | '30:46' => '00000000000010039', // valor_total_titulo_simples 228 | '93:123' => ' ', // uso_exclusivo_febraban_02 229 | '124:240' => ' ', // uso_exclusivo_febraban_03 230 | '47:52' => '000000', // qtde_titulo_cobranca_caucionada 231 | '53:69' => '00000000000000000', // valor_total_titulo_caucionada 232 | '9:17' => ' ', // uso_exclusivo_febraban_01 233 | '70:75' => '000000', // qtde_titulo_cobranca_descontada 234 | '76:92' => '00000000000000000', // valor_total_titulo_descontada 235 | ), 236 | 'trailerArquivo' => array( 237 | '1:3' => '104', // codigo_banco 238 | '4:7' => '9999', // lote_servico 239 | '8:8' => '9', // tipo_registro 240 | '9:17' => ' ', // uso_exclusivo_febraban01 241 | '18:23' => '000001', // qtde_lotes 242 | '24:29' => '000007', // qtde_registros 243 | '30:35' => ' ', // uso_exclusivo_febraban02 244 | '36:240' => ' ', // uso_exclusivo_febraban_03 245 | ), 246 | ); 247 | 248 | foreach ($asserts as $tipo => $campos) { 249 | $vname = "{$tipo}Text"; 250 | foreach ($campos as $pos => $value) { 251 | $aux = explode(':', $pos); 252 | $start = $aux[0] - 1; 253 | $end = ($aux[1] - $aux[0]) + 1; 254 | $this->assertEquals($value, substr($$vname, $start, $end), "[ ] Campo $pos do $tipo"); 255 | } 256 | } 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /tests/Cnab/Remessa/Cnab400/ArquivoTest.php: -------------------------------------------------------------------------------- 1 | configure(array( 12 | 'data_geracao' => new \DateTime('2015-02-01'), 13 | 'data_gravacao' => new \DateTime('2015-02-01'), 14 | 'nome_fantasia' => 'Nome Fantasia da sua empresa', 15 | 'razao_social' => 'Razão social da sua empresa', 16 | 'cnpj' => '11222333444455', 17 | 'banco' => $codigo_banco, //código do banco 18 | 'logradouro' => 'Logradouro da Sua empresa', 19 | 'numero' => 'Número do endereço', 20 | 'bairro' => 'Bairro da sua empresa', 21 | 'cidade' => 'Cidade da sua empresa', 22 | 'uf' => 'SP', 23 | 'cep' => '00000111', 24 | 'agencia' => '1234', 25 | 'conta' => '123', 26 | 'conta_dac' => '1', 27 | )); 28 | 29 | // você pode adicionar vários boletos em uma remessa 30 | $arquivo->insertDetalhe(array( 31 | 'codigo_ocorrencia' => 1, // 1 = Entrada de título, futuramente poderemos ter uma constante 32 | 'nosso_numero' => '12345679', 33 | 'numero_documento' => '12345678', 34 | 'carteira' => '111', 35 | 'especie' => \Cnab\Especie::ITAU_DIVERSOS, // Você pode consultar as especies Cnab\Especie::CEF_OUTROS, futuramente poderemos ter uma tabela na documentação 36 | 'aceite' => 'Z', // "S" ou "N" 37 | 'valor' => 100.39, // Valor do boleto 38 | 'instrucao1' => '', // 1 = Protestar com (Prazo) dias, 2 = Devolver após (Prazo) dias, futuramente poderemos ter uma constante 39 | 'instrucao2' => '', // preenchido com zeros 40 | 'sacado_razao_social' => 'Nome do cliente', // O Sacado é o cliente, preste atenção nos campos abaixo 41 | 'sacado_tipo' => 'cnpj', //campo fixo, escreva 'cpf' (sim as letras cpf) se for pessoa fisica, cnpj se for pessoa juridica 42 | 'sacado_cnpj' => '21.222.333.4444-55', 43 | 'sacado_logradouro' => 'Logradouro do cliente', 44 | 'sacado_bairro' => 'Bairro do cliente', 45 | 'sacado_cep' => '00000-111', 46 | 'sacado_cidade' => 'Cidade do cliente', 47 | 'sacado_uf' => 'BA', 48 | 'data_vencimento' => new \DateTime('2015-02-03'), 49 | 'data_cadastro' => new \DateTime('2015-01-14'), 50 | 'juros_de_um_dia' => 0.10, // Valor do juros de 1 dia' 51 | 'data_desconto' => new \DateTime('2015-02-09'), 52 | 'valor_desconto' => 10.0, // Valor do desconto 53 | 'prazo' => 10, // prazo de dias para o cliente pagar após o vencimento 54 | 'taxa_de_permanencia' => '0', //00 = Acata Comissão por Dia (recomendável), 51 Acata Condições de Cadastramento na CAIXA 55 | 'mensagem' => 'Descrição do boleto', 56 | 'data_multa' => new \DateTime('2015-02-07'), // data da multa 57 | 'valor_multa' => 0.20, // valor da multa 58 | 'tipo_multa' => 'porcentagem', 59 | )); 60 | 61 | $texto = $arquivo->getText(); 62 | $lines = explode("\r\n", trim($texto, "\r\n")); 63 | 64 | $this->assertEquals(3, count($lines)); 65 | $headerText = $lines[0]; 66 | $detalheText = $lines[1]; 67 | //$compl1Text = $lines[2]; 68 | $trailerText = $lines[2]; 69 | 70 | $asserts = array( 71 | 'header' => array( 72 | '1:1' => '0', 73 | '2:2' => '1', 74 | '3:9' => 'REMESSA', 75 | '10:11' => '01', 76 | '12:26' => 'COBRANCA ', 77 | '27:30' => '1234', 78 | '31:32' => '00', 79 | '33:37' => '00123', 80 | '38:38' => '1', 81 | '39:46' => ' ', 82 | '47:76' => str_pad('Nome Fantasia da sua empresa', 30), 83 | '77:79' => '341', 84 | '80:94' => str_pad('BANCO ITAU SA', 15), 85 | '95:100' => '010215', 86 | '101:394' => str_pad(' ', 294), 87 | '395:400' => sprintf('%06d', 1), 88 | ), 89 | 'detalhe' => array( 90 | '1:1' => '1', 91 | '2:3' => '02', // empresa 92 | '4:17' => '11222333444455', // empresa 93 | '18:21' => '1234', 94 | '22:23' => '00', 95 | '24:28' => '00123', 96 | '29:29' => '1', 97 | '30:33' => ' ', 98 | '34:37' => '0000', 99 | '38:62' => str_pad('12345679', 25), 100 | '63:70' => '12345679', 101 | '71:83' => sprintf('%013d', 0), 102 | '84:86' => '0111', 103 | '87:107' => str_pad(' ', 21), 104 | '108:108' => 'I', 105 | '109:110' => '01', 106 | '111:120' => str_pad('12345678', 10), 107 | '121:126' => '030215', 108 | '127:139' => '0000000010039', 109 | '140:142' => '341', 110 | '143:147' => '00000', 111 | '148:149' => '99', 112 | '150:150' => 'Z', 113 | '151:156' => '140115', 114 | '157:158' => ' ', 115 | '159:160' => ' ', 116 | '161:173' => sprintf('%013d', 10), 117 | '174:179' => '090215', 118 | '180:192' => '0000000001000', 119 | '193:205' => sprintf('%013d', 0), 120 | '206:218' => sprintf('%013d', 0), 121 | '219:220' => '02', // 01 = CPF, 02 = CNPJ 122 | '221:234' => '21222333444455', 123 | '235:264' => str_pad('NOME DO CLIENTE', 30), 124 | '265:274' => str_pad(' ', 10), 125 | '275:314' => str_pad('LOGRADOURO DO CLIENTE', 40), 126 | '315:326' => 'BAIRRO DO CL', 127 | '327:334' => '00000111', 128 | '335:349' => str_pad('CIDADE DO CLIEN', 15), 129 | '350:351' => 'BA', 130 | '352:381' => str_pad('NOME FANTASIA DA SUA EMPRESA', 30), 131 | '382:385' => ' ', 132 | '386:391' => '070215', 133 | '392:393' => '10', 134 | '394:394' => ' ', 135 | '395:400' => sprintf('%06d', 2), 136 | ), /* 137 | 'compl1' => array( 138 | '1:1' => '2', 139 | '2:2' => '2', 140 | '3:10' => '07022015', 141 | '11:23' => '0000000000020', 142 | '24:394' => str_repeat(' ', 371), 143 | '395:400' => '000003' 144 | ),*/ 145 | 'trailer' => array( 146 | '001:001' => '9', 147 | '002:394' => str_pad(' ', 393), 148 | '395:400' => sprintf('%06d', 3), 149 | ), 150 | ); 151 | 152 | foreach ($asserts as $tipo => $campos) { 153 | $vname = "{$tipo}Text"; 154 | foreach ($campos as $pos => $value) { 155 | $aux = explode(':', $pos); 156 | $start = $aux[0] - 1; 157 | $end = ($aux[1] - $aux[0]) + 1; 158 | $this->assertEquals($value, substr($$vname, $start, $end), "[ ] $tipo ($pos)"); 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /tests/Cnab/Retorno/Cnab240/ArquivoTest.php: -------------------------------------------------------------------------------- 1 | createRetorno('tests/fixtures/cnab240/retorno_santander.ret'); 11 | $this->assertNotNull($arquivo); 12 | $this->assertNotNull($arquivo->header); 13 | $this->assertNotNull($arquivo->lotes); 14 | $this->assertNotNull($arquivo->trailer); 15 | 16 | $this->assertEquals(11111111, $arquivo->getConta()); 17 | $this->assertEquals(9, $arquivo->getContaDac()); 18 | $this->assertEquals(33, $arquivo->getCodigoBanco()); 19 | 20 | $detalhe = $arquivo->listDetalhes(); 21 | $detalhe = $detalhe[0]; 22 | 23 | $this->assertEquals(1040, $detalhe->segmento_t->nosso_numero); 24 | $this->assertEquals(10, $detalhe->segmento_t->valor_titulo); 25 | } 26 | 27 | public function testArquivoBancoDoBrasilPodeSerLido() 28 | { 29 | $factory = new \Cnab\Factory(); 30 | $arquivo = $factory->createRetorno('tests/fixtures/cnab240/retorno_bb.ret'); 31 | $this->assertNotNull($arquivo); 32 | $this->assertNotNull($arquivo->header); 33 | $this->assertNotNull($arquivo->lotes); 34 | $this->assertNotNull($arquivo->trailer); 35 | 36 | $this->assertEquals(7536, $arquivo->getConta()); 37 | $this->assertEquals(7, $arquivo->getContaDac()); 38 | $this->assertEquals(1, $arquivo->getCodigoBanco()); 39 | $this->assertEquals(3294860, $arquivo->getCodigoConvenio()); 40 | 41 | $this->assertEquals( 42 | \DateTime::createFromFormat('d/m/Y', '21/03/2011'), 43 | $arquivo->getDataGeracao() 44 | ); 45 | 46 | $detalhe = $arquivo->listDetalhes(); 47 | $detalhe = $detalhe[0]; 48 | 49 | $this->assertEquals(40.00, $detalhe->getValorTitulo()); 50 | $this->assertEquals(196, $detalhe->getNossoNumero()); 51 | } 52 | 53 | public function testArquivoCaixaSigcbPodeSerLido() 54 | { 55 | $factory = new \Cnab\Factory(); 56 | $arquivo = $factory->createRetorno('tests/fixtures/cnab240/retorno_cnab240_caixa.ret'); 57 | $this->assertNotNull($arquivo); 58 | $this->assertNotNull($arquivo->header); 59 | $this->assertNotNull($arquivo->lotes); 60 | $this->assertNotNull($arquivo->trailer); 61 | 62 | $this->assertEquals(104, $arquivo->getCodigoBanco()); 63 | 64 | $this->assertEquals( 65 | \DateTime::createFromFormat('d/m/Y', '06/01/2014'), 66 | $arquivo->getDataGeracao() 67 | ); 68 | 69 | $detalhe = $arquivo->listDetalhes(); 70 | $detalhe = $detalhe[0]; 71 | 72 | $this->assertEquals(6, $detalhe->getCodigo()); 73 | $this->assertEquals(80.00, $detalhe->getValorRecebido()); 74 | $this->assertEquals(80.00, $detalhe->getValorTitulo()); 75 | $this->assertEquals(1.25, $detalhe->getValorTarifa()); 76 | $this->assertEquals(0, $detalhe->getValorIOF()); 77 | $this->assertEquals(0, $detalhe->getValorDesconto()); 78 | $this->assertEquals(0, $detalhe->getValorAbatimento()); 79 | $this->assertEquals(0, $detalhe->getValorOutrosCreditos()); 80 | $this->assertEquals(0, $detalhe->getValorMoraMulta()); 81 | $this->assertEquals(null, $detalhe->getNumeroDocumento()); 82 | $this->assertEquals(null, $detalhe->getCarteira()); 83 | $this->assertEquals('0', $detalhe->getAgencia()); 84 | $this->assertEquals(11136997, $detalhe->getNossoNumero()); 85 | $this->assertEquals(new \DateTime('2014-01-02 00:00:00'), $detalhe->getDataVencimento()); 86 | $this->assertEquals(new \DateTime('2014-01-07 00:00:00'), $detalhe->getDataCredito()); 87 | $this->assertEquals(new \DateTime('2014-01-06 00:00:00'), $detalhe->getDataOcorrencia()); 88 | $this->assertEquals(1086, $detalhe->getAgenciaCobradora()); 89 | $this->assertEquals(0, $detalhe->getAgenciaCobradoraDac()); 90 | $this->assertEquals(1, $detalhe->getNumeroSequencial()); 91 | //$this->assertEquals('LIQUIDAÇÃO NORMAL', $detalhe->getCodigoNome()); 92 | $this->assertEquals(true, $detalhe->isBaixa()); 93 | $this->assertEquals(false, $detalhe->isBaixaRejeitada()); 94 | $this->assertEquals(null, $detalhe->getCodigoLiquidacao()); 95 | $this->assertEquals(false, $detalhe->isDDA()); 96 | $this->assertEquals(null, $detalhe->getAlegacaoPagador()); 97 | $this->assertEquals(null, $detalhe->getDescricaoLiquidacao()); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /tests/Cnab/Retorno/Cnab400/ArquivoTest.php: -------------------------------------------------------------------------------- 1 | createRetorno('tests/fixtures/cnab400/retorno-cb030400-bradesco.ret'); 11 | $this->assertNotNull($arquivo); 12 | $this->assertNotNull($arquivo->header); 13 | $this->assertNotNull($arquivo->trailer); 14 | 15 | $this->assertEquals(4466911, $arquivo->getCodigoCedente()); 16 | $this->assertEquals(\Cnab\Banco::BRADESCO, $arquivo->getCodigoBanco()); 17 | 18 | $detalhes = $arquivo->listDetalhes(); 19 | $detalhe = $detalhes[1]; 20 | 21 | $this->assertEquals(new \DateTime('2012-04-12 00:00:00'), $detalhe->getDataVencimento()); 22 | $this->assertEquals(5.0, $detalhe->getValorRecebido()); 23 | $this->assertEquals(97, $detalhe->getNossoNumero()); 24 | $this->assertEquals(15, $detalhe->getNumeroDocumento()); 25 | $this->assertEquals(new \DateTime('2012-04-11 00:00:00'), $detalhe->getDataOcorrencia()); 26 | } 27 | 28 | public function testArquivoBancoDoBrasilCnab400PodeSerLido() 29 | { 30 | $factory = new \Cnab\Factory(); 31 | $arquivo = $factory->createRetorno('tests/fixtures/cnab400/retorno-cnab400-bb.ret'); 32 | 33 | $this->assertNotNull($arquivo); 34 | $this->assertNotNull($arquivo->header); 35 | $this->assertNotNull($arquivo->trailer); 36 | 37 | $this->assertEquals('33448000011113', $arquivo->getCodigoCedente()); 38 | $this->assertEquals(\Cnab\Banco::BANCO_DO_BRASIL, $arquivo->getCodigoBanco()); 39 | 40 | $detalhes = $arquivo->listDetalhes(); 41 | $detalhe = $detalhes[0]; 42 | 43 | $this->assertEquals(25.0, $detalhe->getValorRecebido()); 44 | $this->assertEquals('11122450000000290', $detalhe->getNossoNumero()); 45 | $this->assertEquals(new \DateTime('2015-09-10 00:00:00'), $detalhe->getDataCredito()); 46 | $this->assertEquals(new \DateTime('2015-09-08 00:00:00'), $detalhe->getDataOcorrencia()); 47 | $this->assertTrue($detalhe->isBaixa()); 48 | } 49 | 50 | public function testArquivoItauCnab400PodeSerLido() 51 | { 52 | $factory = new \Cnab\Factory(); 53 | $arquivo = $factory->createRetorno('tests/fixtures/cnab400/retorno-cnab400-itau.ret'); 54 | $this->assertNotNull($arquivo); 55 | $this->assertNotNull($arquivo->header); 56 | $this->assertNotNull($arquivo->trailer); 57 | 58 | $this->assertEquals(\Cnab\Banco::ITAU, $arquivo->getCodigoBanco()); 59 | 60 | $detalhes = $arquivo->listDetalhes(); 61 | 62 | $this->assertEquals(4, count($detalhes)); 63 | $detalhe = $detalhes[0]; 64 | 65 | $this->assertEquals(12345, $arquivo->getConta()); 66 | $this->assertEquals(0, $arquivo->getContaDac()); 67 | $this->assertEquals(341, $arquivo->getCodigoBanco()); 68 | $this->assertEquals(new \DateTime('2013-08-22 00:00:00'), $arquivo->getDataGeracao()); 69 | $this->assertEquals(new \DateTime('2013-06-21 00:00:00'), $arquivo->getDataCredito()); 70 | 71 | $this->assertEquals(6, $detalhe->getCodigo()); 72 | $this->assertEquals(209.97, $detalhe->getValorRecebido()); 73 | $this->assertEquals(389.75, $detalhe->getValorTitulo()); 74 | $this->assertEquals(3.33, $detalhe->getValorTarifa()); 75 | $this->assertEquals(0.1, $detalhe->getValorIOF()); 76 | $this->assertEquals(176.45, $detalhe->getValorDesconto()); 77 | $this->assertEquals(0.19, $detalhe->getValorAbatimento()); 78 | $this->assertEquals(0.18, $detalhe->getValorOutrosCreditos()); 79 | $this->assertEquals(123123.12, $detalhe->getValorMoraMulta()); 80 | $this->assertEquals('1A', $detalhe->getNumeroDocumento()); 81 | $this->assertEquals(109, $detalhe->getCarteira()); 82 | $this->assertEquals('0177', $detalhe->getAgencia()); 83 | $this->assertEquals(231327, $detalhe->getNossoNumero()); 84 | $this->assertEquals(null, $detalhe->getDataVencimento()); 85 | $this->assertEquals(new \DateTime('2013-06-21 00:00:00'), $detalhe->getDataCredito()); 86 | $this->assertEquals(new \DateTime('2013-06-20 00:00:00'), $detalhe->getDataOcorrencia()); 87 | $this->assertEquals(3027, $detalhe->getAgenciaCobradora()); 88 | $this->assertEquals(2, $detalhe->getAgenciaCobradoraDac()); 89 | $this->assertEquals(2, $detalhe->getNumeroSequencial()); 90 | $this->assertEquals('LIQUIDAÇÃO NORMAL', $detalhe->getCodigoNome()); 91 | $this->assertEquals(false, $detalhe->isBaixa()); 92 | $this->assertEquals(false, $detalhe->isBaixaRejeitada()); 93 | $this->assertEquals('B2', $detalhe->getCodigoLiquidacao()); 94 | $this->assertEquals(false, $detalhe->isDDA()); 95 | $this->assertEquals(null, $detalhe->getAlegacaoPagador()); 96 | $this->assertEquals('OUTROS BANCOS – PELA LINHA DIGITÁVEL', $detalhe->getDescricaoLiquidacao()); 97 | 98 | $this->assertNotEmpty($detalhe->getDescricaoLiquidacao()); 99 | 100 | // teste boleto dda e alegacao sacado 101 | $detalhe = $detalhes[1]; 102 | 103 | $this->assertEquals(true, $detalhe->isDDA()); 104 | $this->assertEquals('BOLETO DDA, DIVIDA NÃO RECONHECIDA PELO PAGADOR', $detalhe->getAlegacaoPagador()); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/Cnab/Retorno/CodigoOcorrenciaTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('entrada confirmada', strtolower($codigoOcorrencia->getNome(237, 2, 'cnab400'))); 13 | $this->assertEquals('entrada confirmada', strtolower($codigoOcorrencia->getNome(237, 2))); 14 | $this->assertEquals(null, strtolower($codigoOcorrencia->getNome(237, 25446))); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | getFields() as $field) { 7 | echo " '{$field->pos_start}:{$field->pos_end}' => '{$field->getEncoded()}', // {$field->nome} \n"; 8 | } 9 | }; 10 | 11 | echo "\n"; 12 | echo "$assets = array(\n"; 13 | echo " 'headerArquivo' => array(\n"; 14 | $dumpLine($arquivo->headerArquivo); 15 | echo " ),\n"; 16 | echo " 'headerLote' => array(\n"; 17 | $dumpLine($arquivo->headerLote); 18 | echo " ),\n"; 19 | echo " 'segmentoP' => array(\n"; 20 | $dumpLine($arquivo->detalhes[0]->segmento_p); 21 | echo " ),\n"; 22 | echo " 'segmentoQ' => array(\n"; 23 | $dumpLine($arquivo->detalhes[0]->segmento_q); 24 | echo " ),\n"; 25 | echo " 'segmentoR' => array(\n"; 26 | $dumpLine($arquivo->detalhes[0]->segmento_r); 27 | echo " ),\n"; 28 | echo " 'trailerLote' => array(\n"; 29 | $dumpLine($arquivo->trailerLote); 30 | echo " ),\n"; 31 | echo " 'trailerArquivo' => array(\n"; 32 | $dumpLine($arquivo->trailerArquivo); 33 | echo " ),\n"; 34 | -------------------------------------------------------------------------------- /tests/fixtures/cnab240/retorno_bb.ret: -------------------------------------------------------------------------------- 1 | 00100000 2026599530001760032948600014 0032860000000075367 SAPATARIA E CONFECSOES JIBA BANCO DO BRASIL 22103201102475000025703000000909214318PROCESSAMEN 2 | 00100011T0100020 20026599530001760032948600014 0032860000000075367 SAPATARIA E CONFECSOES JIBA 000000002103201100000000 000000000 3 | 0010001300001T 060032860000000075367 32948600000000196 1 23032011000000000004000237009880 0900000000000000000000000000000000000000000000000000000 000000000000000000000050000 180273294860 4 | 0010001300002U 060000000000000000000000000000000000000000000000000000000000000000000000040000000000000035000000000000000000000000000000002103201123032011 000000000000000 000 5 | 0010001300003T 060032860000000075367 32948600000000236 1 25032011000000000003000033045680 0900000000000000000000000000000000000000000000000000000 000000000000000000000050000 180273294860 6 | 0010001300004U 060000000000000000000000000000000000000000000000000000000000000000000000030000000000000025000000000000000000000000000000002103201123032011 000000000000000 000 7 | 0010001300005T 060032860000000075367 32948600000000244 1 23032011000000000001500104004900 0900000000000000000000000000000000000000000000000000000 000000000000000000000050000 180273294860 8 | 0010001300006U 060000000000000000000000000000000000000000000000000000000000000000000000015000000000000010000000000000000000000000000000002103201123032011 000000000000000 000 9 | 0010001300007T 060032860000000075367 32948600000000249 1 23032011000000000001500104022660 0900000000000000000000000000000000000000000000000000000 000000000000000000000050000 180273294860 10 | 0010001300008U 060000000000000000000000000000000000000000000000000000000000000000000000015000000000000010000000000000000000000000000000002103201123032011 000000000000000 000 11 | 0010001300009T 060032860000000075367 32948600000005048 1 01042011000000000002880033002570 0900000000000000000000000000000000000000000000000000000 000000000000000000000050000 180273294860 12 | 0010001300010U 060000000000000000000000000000000000000000000000000000000000000000000000028800000000000023800000000000000000000000000000002103201123032011 000000000000000 000 13 | 00100015 000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 14 | 00199999 000001000014000000 00000000000000000000000000000 15 | -------------------------------------------------------------------------------- /tests/fixtures/cnab240/retorno_cnab240_caixa.ret: -------------------------------------------------------------------------------- 1 | 10400000 2090183800001990000000000000000000001234204321000000000EMPRESA C ECON FEDERAL 20601201405551100162204000000 RETORNO-PRODUCAO 000 2 | 10400011T0100030 20090183800001990000000000000000000001234204321000000000EMPRESA 00001622060120140000000000 00 3 | 1040001300001T 060000000432100000000 240000000111369979100000000000000002012014000000000008000000010860000000000000000 090000000000000000 000000000000125020101 4 | 1040001300002U 06000000000000000000000000000000000000000000000000000000000000000000000008000000000000008000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 5 | 1040001300003T 060000000432100000000 240000000111381979100000000000000005012014000000000008000000033170000000000000000 090000000000000000 000000000000125020101 6 | 1040001300004U 06000000000000000000000000000000000000000000000000000000000000000000000008000000000000008000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 7 | 1040001300005T 060000000432100000000 240000000111378897100000000000000010012014000000000008000000011920000000000000000 090000000000000000 000000000000125020101 8 | 1040001300006U 06000000000000000000000000001000000000000000000000000000000000000000000007000000000000007000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 9 | 1040001300007T 060000000432100000000 240000000111371256100000000000000010012014000000000008000000011920000000000000000 090000000000000000 000000000000125020101 10 | 1040001300008U 06000000000000000000000000001000000000000000000000000000000000000000000007000000000000007000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 11 | 1040001300009T 060000000432100000000 240000000000222473100000000000000015012014000000000008000000002700000000000000000 090000000000000000 000000000000125020101 12 | 1040001300010U 06000000000000000000000000001000000000000000000000000000000000000000000007000000000000007000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 13 | 1040001300011T 060000000432100000000 240000000111369162100000000000000010012014000000000008000000031280000000000000000 090000000000000000 000000000000125020101 14 | 1040001300012U 06000000000000000000000000001000000000000000000000000000000000000000000007000000000000007000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 15 | 1040001300013T 060000000432100000000 240000000111368980100000000000000010012014000000000008000000036620000000000000000 090000000000000000 000000000000125020101 16 | 1040001300014U 06000000000000000000000000000000000000000000000000000000000000000000000008000000000000008000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 17 | 1040001300015T 060000000432100000000 240000000000319990100000000000000010012014000000000048000000011920000000000000000 090000000000000000 000000000000125020101 18 | 1040001300016U 06000000000000000000000000006000000000000000000000000000000000000000000042000000000000042000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 19 | 1040001300017T 060000000432100000000 240000000000305727100000000000000010012014000000000008000237017950000000000000000 090000000000000000 000000000000270040101 20 | 1040001300018U 06000000000000000000000000001000000000000000000000000000000000000000000007000000000000007000000000000000000000000000000000060120140701201400000701201400000000000000000000000000000000000000000000000000000000000000000000 21 | 10400015 00002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 22 | 10499999 000001000022 23 | -------------------------------------------------------------------------------- /tests/fixtures/cnab240/retorno_santander.ret: -------------------------------------------------------------------------------- 1 | 03300000 2011111111111111456750111111119 001111111 EMPRESA DE TESTE E NOME GRANDEBANCO SANTANDER (BRASIL) S/A 204062014 000077040 2 | 03370311T01 040 2011111111111111001111111 456750111111119 EMPRESA DE TESTE E NOME GRANDE 0000007704062014 3 | 0337031300001T 17456750111111119 00000000010401 0406201400000000000100003303530 002000000000000000 01111111190000000000003240300000000 4 | 0337031300002U 170000000000000000000000000000000000000000000000000000000000000000000000011000000000000011000000000000000000000000000001000406201405062014000000000000000000000000000 000 5 | 03370315 0000020000010000000000005489000000000000000000000000000000000000000000000000000000000000000000000000000076 6 | 03370319 000001000006 7 | -------------------------------------------------------------------------------- /tests/fixtures/cnab400/retorno-cb030400-bradesco.ret: -------------------------------------------------------------------------------- 1 | 02RETORNO01COBRANCA 00000000000004466911COOPERATIVA DE SERVICOS TECNIC237BRADESCO 1104120160000000042 130412 000001 2 | 1020414679200016800000090142000169102 00000000000000000097000000000000000000000000090211041215 00000000000000000097120412000000000050023700523 000000000025200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000 000002 3 | 1020414679200016800000090142000169102 00000000000000000097000000000000000000000000090611041215 00000000000000000097120412000000000050023701420 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000 130412 00000000000000 000003 4 | 1020414679200016800000090142000169102 000000000000000001860000000000000000000000000917110412 00000000000000000186000000000000000000200101886 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000 130412 0000000000 000004 5 | 1020414679200016800000090142000169102 000000000000000001940000000000000000000000000917110412 00000000000000000194000000000000000000200101886 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000 130412 0000000000 000005 6 | 1020414679200016800000090142000169102 000000000000000002080000000000000000000000000917110412 00000000000000000208000000000000000000200101886 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000 130412 0000000000 000006 7 | 1020414679200016800000090142000169102 000000000000000002160000000000000000000000000917110412 00000000000000000216000000000000000000200101886 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000 130412 0000000000 000007 8 | 1020414679200016800000090142000169102 000000000000000002240000000000000000000000000917110412 00000000000000000224000000000000000000200101886 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000 130412 0000000000 000008 9 | 9201237 000000010000000000020000000042 00001000000000500000000000500000010000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000 000009 10 | -------------------------------------------------------------------------------- /tests/fixtures/cnab400/retorno-cnab400-bb.ret: -------------------------------------------------------------------------------- 1 | 02RETORNO01COBRANCA 33448000011113000000EMPRESA TESTE 001BANCO DO BRASIL0809150000017 000000017910400476 1112245 000001 2 | 70000000000000000334480000112131112245 1112245000000029010000001 01900000000000 1806080915 000000000000000250000157045001009150000900000000000000000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000160020000000000000 0000000000000000000000000000000000000000000000001002000002 3 | 9201001 000000000000000000000000000000 000000000000000000000000000000 000000000000000000000000000000 000000000000000000000000000000 000000000000000000000000000000 000003 4 | -------------------------------------------------------------------------------- /tests/fixtures/cnab400/retorno-cnab400-itau.ret: -------------------------------------------------------------------------------- 1 | 02RETORNO01COBRANCA 011100123450 Teste de Retorno 341BANCO ITAU S.A.22081301600BPI00112210613 000001 2 | 10209361352000321017700653730 00231327 109002313270 I06200613 1A00231327 000000000000003897500130272 000000000033300000000000000000000000000000000000001000000000000190000000017645000000002099700000123123120000000000018 21061300000000000000000000000 B2000002 3 | 10209361352000321017700653730 00123442 109001234425 I25200613 00123442 000000000000005650000130272 0000000000333000000000000000000000000000000000000000000000000000000000000197150000000036452000000000000000000000000001 21061300000000000000000000000 1842 B2000003 4 | 10209361352000321017700653730 00211842 109002118429 I06200613 00211842 000000000000003954134103673 000000000033300000000000000000000000000000000000000000000000000000000000000000000000003920900000000000010000000000000 21061300000000000000000000000 BL000004 5 | 10209361352000321017700653730 00237636 109002376365 I06200613 00237636 000000000000005456023728753 000000000033300000000000000000000000000000000000000000000000000000000000020160000000003406700000000000000000000000000 21061300000000000000000000000 B1000005 6 | 9201341 000000000000000000000000000000 000000000000000000000000000000 000000000000000000000000000000 000000000000000000000000000000001120000000400000000189576 000006 7 | --------------------------------------------------------------------------------