Página 2 de 2

Calcular digito verificador

Enviado: 01 Set 2022 19:20
por JoséQuintas
Lá encima pegou a parte errada do manual, mas dá no mesmo.
febraban.png

Calcular digito verificador

Enviado: 02 Set 2022 10:17
por JoséQuintas
febraban.png
No mesmo manual da Febraban tem o cálculo mod10 e mod11.
Nenhum dos dois dá certo.

Calcular digito verificador

Enviado: 02 Set 2022 10:47
por JoséQuintas
Notei um detalhe interessante na conta de energia elétrica:

o valor da conta é 162,32

De acordo com o manual, no código de barras referente ao valor, está constanto 176232

Por coincidência, na separação de números, parece que esse 7 é um dígito de controle do primeiro bloco.

Se for assim, o manual da febraban está furado, e tem mais do que um dígito de controle.

Não entendi mais merd. nenhuma disso.

Calcular digito verificador

Enviado: 02 Set 2022 10:52
por JoséQuintas
Put. que pariu !

Faltou a análise básica:

A conta tem 48 dígitos e não 44.

Com certeza tem um dígito adicional em cada bloco de 11 !!!!

O programador foi elevado ao nível da adivinhação, é froyds !!!!

Calcular digito verificador

Enviado: 02 Set 2022 10:59
por JoséQuintas
digito.png
digito.png (4.73 KiB) Exibido 1982 vezes

Código: Selecionar todos

   cValidar   := Substr( cNumero, 1, 11 ) + ;
                 Substr( cNumero, 13, 11 ) + ;
                 Substr( cNumero, 25, 11 ) + ;
                 Substr( cNumero, 37, 11 )
   cValidar   := Substr( cValidar, 1, 3 ) + Substr( cValidar, 5 )
   cDigito10  := DigitoDocPag10( cValidar )
   cDigito11  := DigitoDocPag11( cValidar )
   cDigito10F := CalculaDigito( cValidar, "10" )
   cDigito11F := CalculaDigito( cValidar, "11" )
É chute, testando de tudo que é jeito, mas parece que deu uma luz, menos na conta de luz kkkkk

Calcular digito verificador

Enviado: 02 Set 2022 11:10
por JoséQuintas

Código: Selecionar todos

   cValidar := ""
   FOR nCont = 1 TO 4
      cParte   := Substr( cNumero, ( nCont - 1 ) * 12 + 1, 12 )
      cValidar += Left( cParte, 11 )
   NEXT
Pequena mudança.
Vou tentar descobrir qual o método de validação de cada bloco
Não sei se vai ajudar na conta de luz.

Calcular digito verificador

Enviado: 02 Set 2022 11:23
por JoséQuintas

Código: Selecionar todos

FUNCTION ValidDocPag( cNumero )

   LOCAL cValidar, cDigito10, cDigito11, cDigito10F, cDigito11F, cParte, nCont

   cValidar := ""
   FOR nCont = 1 TO 4
      cParte   := Substr( cNumero, ( nCont - 1 ) * 12 + 1, 12 )
      @ Row(), Col() SAY Right( cParte, 1 ) + " "
      @ Row(), Col() SAY DigitoDocPag10( Left( cParte, 11 ) ) + " "
      @ Row(), Col() SAY DigitoDocPag11( Left( cParte, 11 ) ) + " "
      @ Row(), Col() SAY CalculaDigito( Left( cParte, 11 ), "10" ) + " "
      @ Row(), Col() SAY CalculaDigito( Left( cParte, 11 ), "11" ) + " "
      cValidar += Left( cParte, 11 )
   NEXT
   cValidar   := Substr( cValidar, 1, 3 ) + Substr( cValidar, 5 )
   cDigito10  := DigitoDocPag10( cValidar )
   cDigito11  := DigitoDocPag11( cValidar )
   cDigito10F := CalculaDigito( cValidar, "10" )
   cDigito11F := CalculaDigito( cValidar, "11" )
   @ Row(), Col() SAY cDigito10 + " "
   @ Row(), Col() SAY cDigito11 + " "
   @ Row(), Col() SAY cDigito10F + " "
   @ Row(), Col() SAY cDigito11F + " "

   RETURN Substr( cNumero, 4, 1 ) $ cDigito10 + cDigito11 + cDigito10F + cDigito11F
teste.png
teste.png (8.64 KiB) Exibido 1980 vezes
Nenhuma conclusão lógica sobre o cálculo do dígito de bloco.
Em cada bloco, o dígito original e os cálculos com cada rotina de cálculo.
No último bloco é o dígito geral, mas nesse bloco o último é o original.
Só na conta de telefone é que os primeiros três blocos tiveram um dígito correto com o cálculo mod10, mas o último bloco não.

Por uma coincidência, na água bateu 1 bloco, na luz dois blocos, e no telefone 3 blocos.

O dígito geral da água bateu com mod11, a do telefone com mod 10

Calcular digito verificador

Enviado: 02 Set 2022 14:47
por gilbertosilverio
Olá Quintas,

Realmente e complicado, os caras não facilitam, por isso montei a rotina pra verificar somente de 11 em 11 caracteres estes pagamentos.

Neste caso estou validando os campos separadamente na digitação, pois esse 6 do 836700000026 e o digito verificador, e o 2 e a centena do valor da conta da enel, no caso 205.61
836700000026 056100481003 222759467913 000343772000
Por mais que você leia esse manual da Febraban, fica difícil fechar todas as possibilidades...

O que preciso e realmente isso, validar se o operador digitou certo, não errou na entrada para evitar problema no pagamento.

Novamente, agradeço sua atenção.

Calcular digito verificador

Enviado: 02 Set 2022 17:53
por JoséQuintas
Acabei de pensar numa possibilidade:

E se.... o dígito de controle NÃO é de cada bloco, e sim acumulado?

Pode ser uma possibilidade, já que o primeiro dígito bateu em todos.

A partir do segundo bloco, sendo acumulado, foi coincidência algum bater a partir do segundo bloco.

Testar essa possibilidade.

Depois volto no geral.

Calcular digito verificador

Enviado: 02 Set 2022 17:55
por JoséQuintas
gilbertosilverio escreveu:Por mais que você leia esse manual da Febraban, fica difícil fechar todas as possibilidades...
digito.png
Que tal acima? resto 1 então o dígito é zero.
Cadê a explicação de como o 1 virou zero.

Calcular digito verificador

Enviado: 02 Set 2022 18:07
por JoséQuintas
Não vai de jeito nenhum.

Mas então...

Como o manual da Febraban descreve 44 dígitos se são 48 ?

O problema começa aí, a quantidade de dígitos já não é a mesma.

Calcular digito verificador

Enviado: 03 Set 2022 05:31
por gilbertosilverio
Ola Quintas,

Analisando o código do harbourboleto, observei que cada banco tem sua forma de calculo da mod11, creio que seja o mesmo para esses pagamentos a concessionarias, cada qual "inventa" sua maneira, e realmente uma Torre de Babel, cada um fala uma língua.

Portanto, creio que para conseguir fazer funcionar e necessário analisar caso a caso...

Código: Selecionar todos


      // Monta C¢digo de Barras (p/ Banco)
      cDGCB := DC_Mod11(::cCodBco, 9, .T., ::cCodBco + ::cTipoMoeda + cFatorVenc + STRZERO(::nValor * 100, 10) + cCpoLivre)
      cCodBar := ::cCodBco + ::cTipoMoeda + cDGCB + cFatorVenc + STRZERO(::nValor * 100, 10) + cCpoLivre
      //              3           1            1        4                     10                   25
      nY := 0
      FOR nX := 1 TO LEN(cCodBar) STEP 2
          ::Merge(STRZERO(nY++, 2), SUBSTR(cCodBar, nX, 2))
      NEXT
      // Monta Representação Numérica do Código de Barras
      cC1RN := ::cCodBco + ::cTipoMoeda + LEFT(cCpoLivre, 5)
      cC1RN := cC1RN + DC_Mod10(::cCodBco, cC1RN)

      cC2RN := SUBSTR(cCpoLivre, 6, 10)
      cC2RN += DC_Mod10(::cCodBco, cC2RN)

      cC3RN := SUBSTR(cCpoLivre, 16, 20)
      cC3RN += DC_Mod10(::cCodBco, cC3RN)

      cC4RN :=cDGCB

      cC5RN :=cFatorVenc + STRZERO(::nValor * 100, 10)

      cRNCB := LEFT(cC1RN, 5) + "." + SUBSTR(cC1RN, 6) + " " + LEFT(cC2RN, 5) + "." +;
            SUBSTR(cC2RN, 6) + " " + LEFT(cC3RN, 5) + "." + SUBSTR(cC3RN, 6) + "  " + cC4RN + "  " + cC5RN
      ::Merge("LINDIG", cRNCB)
....

// Retorna Dígito de Controle Módulo 10                                       //

FUNCTION DC_Mod10( cCodBco, mNMOG )

   LOCAL mVLDG, mSMMD, mCTDG, mRSDV, mDCMD
   mSMMD:=0
   FOR mCTDG := 1 TO LEN(mNMOG)
      mVLDG := VAL(SUBSTR(mNMOG, LEN(mNMOG) - mCTDG + 1, 1)) * IF(MOD(mCTDG,2) == 0, 1, 2)
      mSMMD += mVLDG - IF(mVLDG > 9, 9, 0)
   NEXT
   mRSDV := MOD(mSMMD, 10)
   mDCMD := IF(mRSDV == 0, "0", STR(10 - mRSDV, 1))

RETURN mDCMD

/* -------------------------------------------------------------------------- */
// Retorna Digito de Controle Modulo 11 (p/ Banco)                            //
// bradesco -> DC_Mod11("237", 7, .F., carteira+agencia+nossonumero)

FUNCTION DC_Mod11( mCDBC, mBSDG, mFGCB, mNMOG, lMult10 )

   LOCAL mSMMD, mCTDG, mSQMP, mRSDV, mDCMD
   DEFAULT mFGCB TO .F., lMult10 TO .F.
   mSMMD := 0
   mSQMP := 2

   FOR mCTDG := 1 TO LEN(mNMOG)
       mSMMD += VAL(SUBSTR(mNMOG, LEN(mNMOG) - mCTDG + 1, 1)) * (mSQMP)
       mSQMP := IF(mSQMP == mBSDG, 2, mSQMP+1)
   NEXT
   IF lMult10
      mSMMD *= 10
   ENDIF
   mRSDV := MOD(mSMMD, 11)
   IF mFGCB
      mDCMD := IF(mRSDV > 9 .OR. mRSDV < 2, "1", STR(11 - mRSDV, 1))
   ELSE
      IF mCDBC == "001"        // Brasil
         mDCMD := IF(mRSDV == 0, "0", IF(mRSDV == 1, "X", STR(11 - mRSDV, 1)))
      ELSEIF mCDBC like "(008|033|353)"  //Santander Banespa
         mDCMD := IF(mRSDV < 2, "0", IF(mRSDV == 10, "1", STR(11 - mRSDV, 1)))
       //mDCMD := IF(mRSDV == 0, "0", IF(mRSDV == 1, "X", STR(11 - mRSDV, 1)))
      ELSEIF mCDBC=="104"      // Caixa
         mRSDV := 11 - mRSDV
         mDCMD := IF(mRSDV > 9, "0", STR(mRSDV, 1))
      ELSEIF mCDBC == "237"    // Bradesco
         mDCMD := IF(mRSDV == 0, "0", IF(mRSDV == 1, "P", STR(11 - mRSDV, 1)))
      ELSEIF mCDBC == "341"    // Itau
         mDCMD := IF(mRSDV == 11, "1", STR(11 - mRSDV, 1))
      ELSEIF mCDBC == "409"    // Unibanco
         mDCMD := IF(mRSDV == 0 .OR. mRSDV == 10, "0", STR(mRSDV, 1))
      ELSEIF mCDBC == "422"    // Safra
         mDCMD := IF(mRSDV==0, "1", IF(mRSDV == 1, "0", STR(11 - mRSDV, 1)))
      ENDIF
   ENDIF

RETURN mDCMD

/* -------------------------------------------------------------------------- */
// Retorna Dígito de Controle Módulo Especial                                 //

FUNCTION DC_ModEsp( cCodBco, mNMOG )
   LOCAL mVLDG, mSMMD, mCTDG, mSQMP, mRSDV, mDCMD:=0

   IF cCodBco == "033"  // Banespa
      mSMMD:=0
      mSQMP:=3
      FOR mCTDG := 1 TO LEN(mNMOG)
          mVLDG := VAL(SUBSTR(mNMOG, LEN(mNMOG) - mCTDG + 1, 1)) * (mSQMP)
          mSMMD += mVLDG - (INT(mVLDG / 10) * 10)
          mSQMP := IF(mSQMP == 3, 7, IF(mSQMP == 7, 9, IIF(mSQMP == 9, 1, 3)))
      NEXT
      mRSDV := mSMMD - (INT(mSMMD / 10) * 10)
      mDCMD := IIF(mRSDV == 0, 0, 10 - mRSDV)
   ENDIF
RETURN str(mDCMD,1)


Calcular digito verificador

Enviado: 03 Set 2022 17:40
por JoséQuintas
febraban.png
Nenhuma novidade, apenas no manual da Febraban tem este modelo de documento, que mostra 48 dígitos.
Ou seja, o manual diz código de barras com 44 dígitos, mas mostra no impresso com 48 dígitos.
gilbertosilverio escreveu:Analisando o código do harbourboleto, observei que cada banco tem sua forma de calculo da mod11, creio que seja o mesmo para esses pagamentos a concessionarias, cada qual "inventa" sua maneira, e realmente uma Torre de Babel, cada um fala uma língua.
Portanto, creio que para conseguir fazer funcionar e necessário analisar caso a caso...
Não sei se pensou nisto, mas ....
Nesse caso é por sorteio, depende de cada empresa/cidade/uf, pois depende do banco que foi contratado, e não do tipo de conta.
Isso pode significar criar uma tabela, sem limites.

Calcular digito verificador

Enviado: 03 Set 2022 17:55
por JoséQuintas
barras.png
Tem essa também, se seguir o padrão do boleto.
Código de barras é uma coisa, e linha digitável é outra.

Calcular digito verificador

Enviado: 05 Set 2022 18:12
por JoséQuintas
Achei uma referência como luz.

Código: Selecionar todos

PROCEDURE Main

   LOCAL cAgua     := "82630000000565760097914034812984770196266947635"
   LOCAL cLuz      := "83680000001762320048100942155127816001453291153"
   LOCAL cTelefone := "84610000000510140082089699479218581554719226099"

   IF Modulo11( "34191000000000000001753980229122525005423000" ) != "1"
      ? 'Função modulo11 está com erro!"
   ENDIF
   IF Modulo10( "399903512" ) != "8"
      ? "Função modulo10 está com erro!"
   ENDIF

   ? LinhaToBarra( cAgua )
   ? LinhaToBarra( cLuz )
   ? LinhaToBarra( cTelefone )
   Inkey(0)

   RETURN


FUNCTION LinhaToBarra( linha )

   LOCAL Barra

		barra  = Substr( linha, 1, 4 ) + ;
               Substr( linha, 33, 15 ) + ;
               Substr( linha, 5, 5 ) + ;
               Substr( linha, 11, 10 ) + ;
               Substr( linha, 22, 10 )
		IF Modulo11( Substr( barra, 1, 4 ) + Substr( barra, 6, 39 ) ) != Substr( barra, 5, 1 )
			? "Digito verificador invalido"
      ENDIF

   RETURN barra

FUNCTION BarraToLinha( barra )

   LOCAL Campo1, Campo2, Campo3, Campo4, Campo5, Linha

   Campo1 := Substr( barra, 1, 4 ) + Substr( barra, 20, 1 ) + Substr( barra, 21, 4 )
   Campo2 := Substr( barra, 25, 5 ) + Substr( Barra, 25 + 5, 5 )
   Campo3 := Substr( Barra, 35, 5 ) + Substr( Barra, 35 + 5, 5 )
   Campo4 := Substr( Barra, 5, 1 )
   Campo5 := Substr( Barra, 6, 14 )

   IF Modulo11(  Substr( Barra, 1, 4 ) + Substr( Barra, 6, 99 ) ) != campo4
      ? "Digito invalido"
   ENDIF
   Linha := Campo1 + Modulo10( campo1 ) + ;
            Campo2 + Modulo10( campo2 ) + ;
            Campo3 + Modulo10( campo3 ) + ;
            Campo4 + Campo5

   RETURN Linha

STATIC FUNCTION Modulo10( cNumero )

   LOCAL cChar, nSoma := 0, nValor, nResto, cDigito

   FOR EACH cChar IN cNumero DESCEND
      nValor := Val( cChar ) * iif( mod( cChar:__EnumIndex, 2 ) == 0, 1, 2 )
      nSoma += nValor - iif( nValor > 9, 9, 0 )
   NEXT
   nResto := MOD( nSoma, 10 )
   cDigito := Str( iif( nResto == 0, 0, 10 - nResto ), 1 )

   RETURN cDigito

STATIC FUNCTION Modulo11( cNumero )

   LOCAL cChar, nSoma := 0, nResto, cDigito, nMultiplica := 2

   cNumero := AllTrim( cNumero )
   FOR EACH cChar IN cNumero DESCEND
      nSoma += Val( cChar ) * nMultiplica
      nMultiplica := iif( nMultiplica == 9, 2, nMultiplica + 1 )
   NEXT
   nResto := Mod( nSoma, 11 )
   cDigito := Str( iif( nResto == 0, 1, iif( nResto == 1, 0, 11 - nResto ) ), 1 )

   RETURN cDigito
Ao que parece, assim seria para o Banco Itaú.
Só uma das contas bate, provavelmente a que é no Itaú, ou que tem cálculo igual.