Skip to content

Commit

Permalink
itau pix registro
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardokum committed Nov 23, 2023
1 parent a605599 commit 111b3c9
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 23 deletions.
2 changes: 1 addition & 1 deletion exemplos/btg_boleto.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
'instrucoes' => ['instrucao 1', 'instrucao 2', 'instrucao 3'],
'aceite' => 'S',
'especieDoc' => 'DM',
'pix_qrcode' => '00020126330014br.gov.bcb.pix01111335366962052040000530398654040.805802BR5919NOME6014CIDADE62580520LKH2021102118215467250300017br.gov.bcb.brcode01051.0.063044D24',
'pix_qrcode' => '00020104141234567890123426660014BR.GOV.BCB.PIX014466756C616E6F32303139406578616D706C652E636F6D27300012BR.COM.OUTRO011001234567895204000053039865406123.455802BR5915NOMEDORECEBEDOR6008BRASILIA61087007490062530515RP12345678-201950300017BR.GOV.BCB.BRCODE01051.0.080450014BR.GOV.BCB.PIX0123PADRAO.URL.PIX/0123ABCD81390012BR.COM.OUTRO01190123.ABCD.3456.WXYZ6304EB76',
]);

$pdf = new Eduardokum\LaravelBoleto\Boleto\Render\Pdf();
Expand Down
2 changes: 1 addition & 1 deletion exemplos/btg_remessa.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
'instrucoes' => ['instrucao 1', 'instrucao 2', 'instrucao 3'],
'aceite' => 'S',
'especieDoc' => 'DM',
'pix_qrcode' => '00020126330014br.gov.bcb.pix01111335366962052040000530398654040.805802BR5919NOME6014CIDADE62580520LKH2021102118215467250300017br.gov.bcb.brcode01051.0.063044D24',
'pix_qrcode' => '00020104141234567890123426660014BR.GOV.BCB.PIX014466756C616E6F32303139406578616D706C652E636F6D27300012BR.COM.OUTRO011001234567895204000053039865406123.455802BR5915NOMEDORECEBEDOR6008BRASILIA61087007490062530515RP12345678-201950300017BR.GOV.BCB.BRCODE01051.0.080450014BR.GOV.BCB.PIX0123PADRAO.URL.PIX/0123ABCD81390012BR.COM.OUTRO01190123.ABCD.3456.WXYZ6304EB76',
]);

$remessa = new \Eduardokum\LaravelBoleto\Cnab\Remessa\Cnab240\Banco\Btg([
Expand Down
14 changes: 13 additions & 1 deletion src/Cnab/Remessa/Cnab400/Banco/Itau.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Itau extends AbstractRemessa implements RemessaContract
const OCORRENCIA_ALT_VENC_SUSTAR_PROTESTO = '37';
const OCORRENCIA_NAO_CONCORDA_SACADO = '38';
const OCORRENCIA_DISPENSA_JUROS = '47';
const OCORRENCIA_REMESSA_PIX = '71';
const INSTRUCAO_SEM = '00';
const INSTRUCAO_DEVOL_VENC_5 = '02';
const INSTRUCAO_DEVOL_VENC_30 = '03';
Expand Down Expand Up @@ -178,6 +179,8 @@ public function addBoleto(BoletoContract $boleto)
$this->iniciaDetalhe();
}

$pix = $boleto->validarPix();

$this->add(1, 1, '1');
$this->add(2, 3, strlen(Util::onlyNumbers($this->getBeneficiario()->getDocumento())) == 14 ? '02' : '01');
$this->add(4, 17, Util::formatCnab('9', Util::onlyNumbers($this->getBeneficiario()->getDocumento()), 14));
Expand All @@ -193,7 +196,7 @@ public function addBoleto(BoletoContract $boleto)
$this->add(84, 86, Util::formatCnab('9', $this->getCarteiraNumero(), 3));
$this->add(87, 107, '');
$this->add(108, 108, 'I');
$this->add(109, 110, self::OCORRENCIA_REMESSA); // REGISTRO
$this->add(109, 110, $pix ? self::OCORRENCIA_REMESSA_PIX : self::OCORRENCIA_REMESSA); // REGISTRO ou REGISTRO PIX
if ($boleto->getStatus() == $boleto::STATUS_BAIXA) {
$this->add(109, 110, self::OCORRENCIA_PEDIDO_BAIXA); // BAIXA
}
Expand Down Expand Up @@ -258,6 +261,15 @@ public function addBoleto(BoletoContract $boleto)
$this->add(395, 400, Util::formatCnab('9', $this->iRegistros + 1, 6));
}

if ($pix) {
$this->iniciaDetalhe();
$this->add(1, 1, '3');
$this->add(2, 78, Util::formatCnab('X', $boleto->getPixChave(), 77));
$this->add(79, 142, Util::formatCnab('X', $boleto->getID(), 35));
$this->add(143, 394, '');
$this->add(395, 400, Util::formatCnab('9', $this->iRegistros + 1, 6));
}

return $this;
}

Expand Down
73 changes: 56 additions & 17 deletions src/Cnab/Retorno/Cnab400/Banco/Itau.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace Eduardokum\LaravelBoleto\Cnab\Retorno\Cnab400\Banco;

use Eduardokum\LaravelBoleto\Cnab\Retorno\Cnab400\AbstractRetorno;
use Eduardokum\LaravelBoleto\Contracts\Boleto\Boleto as BoletoContract;
use Illuminate\Support\Arr;
use Eduardokum\LaravelBoleto\Util;
use Eduardokum\LaravelBoleto\Contracts\Cnab\RetornoCnab400;
use Eduardokum\LaravelBoleto\Exception\ValidationException;
use Eduardokum\LaravelBoleto\Util;
use Illuminate\Support\Arr;
use Eduardokum\LaravelBoleto\Cnab\Retorno\Cnab400\AbstractRetorno;
use Eduardokum\LaravelBoleto\Contracts\Boleto\Boleto as BoletoContract;

class Itau extends AbstractRetorno implements RetornoCnab400
{
Expand Down Expand Up @@ -176,12 +176,12 @@ class Itau extends AbstractRetorno implements RetornoCnab400
protected function init()
{
$this->totais = [
'liquidados' => 0,
'entradas' => 0,
'baixados' => 0,
'liquidados' => 0,
'entradas' => 0,
'baixados' => 0,
'protestados' => 0,
'erros' => 0,
'alterados' => 0,
'erros' => 0,
'alterados' => 0,
];
}

Expand Down Expand Up @@ -214,8 +214,11 @@ protected function processarHeader(array $header)
*/
protected function processarDetalhe(array $detalhe)
{
$d = $this->detalheAtual();
if ($this->rem(1, 1, $detalhe) == 3) {
return $this->processarPix($detalhe);
}

$d = $this->detalheAtual();
$d->setCarteira($this->rem(83, 85, $detalhe))
->setNossoNumero($this->rem(86, 94, $detalhe))
->setNumeroDocumento($this->rem(117, 126, $detalhe))
Expand Down Expand Up @@ -271,14 +274,50 @@ protected function processarDetalhe(array $detalhe)
protected function processarTrailer(array $trailer)
{
$this->getTrailer()
->setQuantidadeTitulos((int)$this->rem(18, 25, $trailer) + (int)$this->rem(58, 65, $trailer) + (int)$this->rem(178, 185, $trailer))
->setValorTitulos((float)Util::nFloat($this->rem(221, 234, $trailer) / 100, 2, false))
->setQuantidadeErros((int)$this->totais['erros'])
->setQuantidadeEntradas((int)$this->totais['entradas'])
->setQuantidadeLiquidados((int)$this->totais['liquidados'])
->setQuantidadeBaixados((int)$this->totais['baixados'])
->setQuantidadeAlterados((int)$this->totais['alterados']);
->setQuantidadeTitulos((int) $this->rem(18, 25, $trailer) + (int) $this->rem(58, 65, $trailer) + (int) $this->rem(178, 185, $trailer))
->setValorTitulos((float) Util::nFloat($this->rem(221, 234, $trailer) / 100, 2, false))
->setQuantidadeErros((int) $this->totais['erros'])
->setQuantidadeEntradas((int) $this->totais['entradas'])
->setQuantidadeLiquidados((int) $this->totais['liquidados'])
->setQuantidadeBaixados((int) $this->totais['baixados'])
->setQuantidadeAlterados((int) $this->totais['alterados']);

return true;
}

/**
* @param array $detalhe
* @return bool
* @throws ValidationException
*/
private function processarPix(array $detalhe)
{
$d = $this->getDetalhe($this->increment - 1);

$aErrorPix = [
'000' => null,
'001' => 'VALOR MAIOR QUE O MÁXIMO PERMITIDO',
'002' => 'NÃO É COMPATÍVEL COM O CNPJ INFORMADO',
'003' => 'CHAVE INVÁLIDA',
'004' => 'CHAVE SEM CADASTRO NA DICT',
'005' => 'CHAVE NÃO CADASTRADA NO MESMO CNPJ DA AG/CONTA DA REMESSA.',
'006' => 'EMISSÃO DE QR CODE NÃO PERMITIDA',
'007' => 'DATA DE DESCONTO MAIOR QUE A DATA DE VENCIMENTO',
'008' => 'IDLOCATION JÁ ESTÁ SENDO UTILIZADO POR OUTRA COBRANÇA PIX.',
'009' => 'LOCATION CRIADA PARA TIPO “COBRANÇA COM VENCIMENTO”',
'010' => 'BOLETO COM PIX NÃO É PERMITIDO PARA BOLETO COM PAGAMENTO PARCIAL',
'011' => 'BOLETO COM PIX NÃO É PERMITIDO PARA A CARTEIRA DO BOLETO',
'999' => 'PIX NÃO EMITIDO POR PROLEMAS NA PLATAFORMA. ENTRE EM CONTATO COM AS ÁREAS DE SUPORTE DO ITAÚ UNIBANCO',
];

$d->setPixQrCode(trim($this->rem(2, 391, $detalhe)));
if ($decoded = Util::decodePixCopiaECola($d->getPixQrCode())) {
$d->setPixChave(Arr::get($decoded, '26.01'));
$d->setPixChaveTipo(Util::tipoChavePix($d->getPixChave()));
$d->setId(Arr::get($decoded, '62.05'));
}
$d->setError(Util::appendStrings($d->getError(), $aErrorPix[sprintf('%03s', $this->rem(392, 394, $detalhe))]));

return false;
}
}
71 changes: 69 additions & 2 deletions src/Util.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use NumberFormatter;
use Illuminate\Support\Str;
use Illuminate\Http\UploadedFile;
use Eduardokum\LaravelBoleto\Boleto\AbstractBoleto;
use Eduardokum\LaravelBoleto\Exception\ValidationException;
use Eduardokum\LaravelBoleto\Contracts\Boleto\Boleto as BoletoContract;

Expand Down Expand Up @@ -1259,7 +1260,7 @@ public static function gerarPixCopiaECola($pix, $valor, $id, Pessoa $beneficiari

$gui = $line('00', 'br.gov.bcb.pix');
$key = $line('01', $pix);
$txid = $line('05', $id);
$txId = $line('05', $id);
$payload = $line('00', '01');
$payload .= $line('01', '12');
$payload .= $line('26', $gui.$key);
Expand All @@ -1269,11 +1270,77 @@ public static function gerarPixCopiaECola($pix, $valor, $id, Pessoa $beneficiari
$payload .= $line('58', 'BR');
$payload .= $line('59', $beneficiario->getNome());
$payload .= $line('60', $beneficiario->getCidade());
$payload .= $line('62', $txid);
$payload .= $line('62', $txId);

return $payload.$crc16($payload);
}

/**
* Função baseada no projeto
* https://github.com/renatomb/decoder_brcode_pix/blob/main/funcoes.php
* @param $pixCopiaECola
* @return array|null
*/
public static function decodePixCopiaECola($pixCopiaECola)
{
$aPix = [];
$i = 0;
while ($i < strlen($pixCopiaECola)) {
$code = substr($pixCopiaECola, $i, 2);
$i += 2;
$size = intval(substr($pixCopiaECola, $i, 2));
if (! is_numeric($size)) {
return null;
}
$i += 2;
$valor = substr($pixCopiaECola, $i, $size);
$i += $size;
if (preg_match('/^\d{4}.+$/', $valor) && ($code != 54)) {
$aPix[$code] = self::decodePixCopiaECola($valor);
} else {
$aPix[$code] = $valor;
}
}

return $aPix;
}

/**
* @param $chave
* @return string|null
*/
public static function tipoChavePix($chave)
{
if (is_null($chave)) {
return null;
}

$parametro = trim($chave);
if (filter_var($parametro, FILTER_VALIDATE_EMAIL)) {
return AbstractBoleto::TIPO_CHAVEPIX_EMAIL;
}

if (Util::validarCnpj($parametro)) {
return AbstractBoleto::TIPO_CHAVEPIX_CNPJ;
}

if (Util::validarCpf($parametro)) {
return AbstractBoleto::TIPO_CHAVEPIX_CPF;
}

// Verificar se é um telefone
if (preg_match('/^(\+\d{2})?\(?\d{2}\)?[-.\s]?(\d\s?)?\d{4}[-.\s]?\d{4}$/', $parametro)) {
return AbstractBoleto::TIPO_CHAVEPIX_CELULAR;
}

// Verificar se é um UUID
if (preg_match('/^[a-fA-F0-9]{32}$/', $parametro) && (ctype_xdigit($parametro))) {
return AbstractBoleto::TIPO_CHAVEPIX_ALEATORIA;
}

return null;
}

/**
* @param $str
* @return bool
Expand Down
2 changes: 1 addition & 1 deletion tests/Boleto/BoletoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ public function testBoletoBBWithQRCodePixCopiaECola()
'instrucoes' => ['instrucao 1', 'instrucao 2', 'instrucao 3'],
'aceite' => $this->aceite(),
'especieDoc' => 'DM',
'pix_qrcode' => '00020126330014br.gov.bcb.pix01111335366962052040000530398654040.805802BR5919NOME6014CIDADE62580520LKH2021102118215467250300017br.gov.bcb.brcode01051.0.063044D24',
'pix_qrcode' => '00020104141234567890123426660014BR.GOV.BCB.PIX014466756C616E6F32303139406578616D706C652E636F6D27300012BR.COM.OUTRO011001234567895204000053039865406123.455802BR5915NOMEDORECEBEDOR6008BRASILIA61087007490062530515RP12345678-201950300017BR.GOV.BCB.BRCODE01051.0.080450014BR.GOV.BCB.PIX0123PADRAO.URL.PIX/0123ABCD81390012BR.COM.OUTRO01190123.ABCD.3456.WXYZ6304EB76',
]);

$boletoHtml = $boleto->renderHTML();
Expand Down

0 comments on commit 111b3c9

Please sign in to comment.