Jump to content
Fivewin Brasil

fladimir

Membros
  • Posts

    364
  • Joined

  • Last visited

  • Days Won

    12

Everything posted by fladimir

  1. Muito legal Dorneles... obrigado por compartilhar. O link mostra as diferenças nas TAGs etc. Agora vc teria o link da documentação (acho q no site da SEFAZ deve ter vou ver) pra confirmar sobre a questão do Status de Serviço se realmente deixará de funcionar?
  2. Pelo ACBr já tem pra usar o ambiente 4.0 em homologação, produção não testei nem sei dizer se já esta liberado, mas homologação em algumas UFs já. Alguém tem o manual da nova versão 4.0? Saberia confirmar se aboliram o Status de Serviço nessa versão? Parece q ia parar o Status de Serviço.
  3. Mas no caso no dia a dia... tipo to faturando: Faturamento 000001 100 sacos de Cimento etc. Ai no final escolho entrega futura ou algo do tipo pra informar q vai ser atendido depois? Ai depois posso ir informando o q foi atendido/saiu pra entrega? Pq via de regra muitos pedidos serão atendidos 100% na hora do faturamento, alguns que ficarão pendentes total ou parciais para entrega futura correto?
  4. Bom dia, Não utilizo a parte de retorno do ACBr ainda, será q não é a versão? Poderia olhar no Changelog ver se alguém passou por isso ou analisar tudo q foi implementado relativo a isso.
  5. vc tem q linkar junto a lib CT, se estiver usando harbour coloca hbct.hbc
  6. Show de bola... assisti o vídeo parabéns... Realmente pelo q pesquisei o Windev é top e com muitos recursos... []´s
  7. Vc altera, salva e depois roda o comando pra alterar a data do arquivo. função SetFDati() SetFDaTi() Sets the last change date and time of a file. Syntax SetFDaTi( <cFileName> , ; [<dFileDate>], ; [<cFileTime>] ) --> lSuccess Arguments <cFileName> This is a character string holding the name of the file to set date and time for. It must include path and file extension. If the path is omitted from <cFileName>, the file is searched in the current directory only. <dFileDate> This is the date value to be set. It defaults to the return value of Date(). <cFileTime> This is a time formatted string that defines the new file time. It defaults to Time(). Return The function returns .T. (true) if the file date and time is set, otherwise .F. (false) is returned.
  8. E ai Luis alguma novidade? Tem um cliente meu q precisa de algo básico, ele quer cadastrar os quartos, valores das diárias e controlar se tem vaga ou não / reservas
  9. Olá pessoal... com relação a API do Google ela é FREE até X solicitações por dia... ou seja, eu implementei o código q varre a tabela de clientes e pelo endereço pega as coordenadas e depois armazena pra em uma próxima utilização não ter q pesquisar novamente e agilizar a montagem do mapa com os cliente marcadados, mas devido N testes começou em determinado momento não funcionar e ao debugar e olhar o conteúdo q retornava a mensagem era do Google q havia atingido o limite e pra acessar determinado URL deles onde cadastra o projeto/sistema nosso e tem os planos exemplo 4 dolares libera 10.000 acessos e por ai vai... Minha dúvida é se adotando a solução do colega via Google Earth elimina essa limitação, pq se colocamos isso em nossos sistemas e os clientes começam a utilizar (não sei como eles controlam) mas dependendo o uso irá atingir o limite do Free, tudo bem q no outro dia libera (como hj já testei e esta liberado), mas o fato é q o limite da API do Google existe, alguém saberia responder?
  10. Vc tem a planilha de homologação do Sicredi? Caso não posso te enviar (não sei se pode anexar aki) Fora isto o q eu faço nessa parte é determinar a o "Prefixo" do nosso número q é variavel entre 2 e 9, nós q escolhemos, não tem controle sobre isto, na época q homologuei eles orientaram a usar do 3 em diante, pq o 2 eles usam no programa deles, então eu uso assim, o q começa com 3 é destinado a uma determinada situação no cliente exemplo, vendas externas, os q começam com 6 outra situação, pq como é livre a utilização entre 2 a 9 o prefixo, o q manda é o sequencial, exemplo: 2 00001 = prefixo 2 geralmente usado pela emissão própria do Sicredi, mas podemos usar tb, porém orientam usar do 3 em diante para não dar conflito então... faixa de numeração 3 00001, 3 00002, ... 3 00015, ... 3 99998, 3 99999, 4 00001 e por ai vai... até 9 99999 Qual o problema q ocorre? No meu caso eu starto a numeração inicial em 3 00000 e o sistema vai na sequencia.
  11. Então eu tinha escrito da possibilidade, mas depois li com mais calma e vi q vc definiu a quantidade de casas no ACBr. O ACBr / Webservice do governo (não sei precisar qual, acredito q o Governo) permite até 0,004 de diferença em um item (pelo menos em testes no valor do IBPT por item) cheguei a este resultado, faça o seguinte, faça testes a nível de arquivo texto alimentado / alterando manualmente até chegar nos valores q vc verifica q vai passar depois ajusta no sistema. Eu parei de trabalhar com Round nessa parte de calculos nos itens, faço os calculos e Trunco na 4 casa e mando bala e jogo a soma nas tags total, ai não tive mais problemas.
  12. Segue exemplo usado para homologação SICREDI. ******************************************************************************** STATIC FUNCTION ExemploCBXBoleto() // SICREDI LOCAL oCBX, oBoleto FOR n := 1 to 10 Alert( 'Fazendo o Boleto de No. ' + strzero(n,3)) // Necessário efetuar download da lib TOleAuto em http://www.cobrebem.com/downloads/cbx/hbole.zip oCBX := TOleAuto():New("CobreBemX.ContaCorrente") * oCBX := CreateObject("CobreBemX.ContaCorrente") xTipo:= Valtype(oCBX) If Valtype( oCBX ) <> "O" Alert( "Erro...") Endif /* Nao usei oCBX:PadroesBoleto:PadroesBoletoImpresso:ArquivoLogotipo := VP_PATH+"Imagens\033.jpg" oCBX:PadroesBoleto:PadroesBoletoImpresso:Layoutboleto:=vp_path+"Imagens\PadraoReciboPersonalizado" oCBX:PadroesBoleto:PadroesBoletoImpresso:layoutboleto:=vp_path+"Imagens\PadraocomcomprovantedeEntrega.txt" *-- Para imprimir 3 em 1 folha oCBX:PadroesBoleto:PadroesBoletoImpresso:LayoutBoleto := "CarnetReciboLateralEsquerda" */ // Monta arquivo de licenca Sicredi 748 - tipo C = 03 Sem Registro oCBX:ArquivoLicenca := "c:\CobreBemX\81171215168-748-C.conf" // Outras Configuracoes oCBX:PadroesBoleto:PadroesBoletoImpresso:ArquivoLogotipo := curdirsys()+"Imagens\banner.gif" oCbx:PadroesBoleto:PadroesBoletoImpresso:margemsuperior:=00 oCBX:PadroesBoleto:PadroesBoletoImpresso:CaminhoImagensCodigoBarras := curdirsys()+"Imagens\" oCBX:PadroesBoleto:InstrucoesCaixa := ' Conceder desconto de 5%' //vn_mensagem oCBX:PadroesBoleto:Demonstrativo := ' Referentes a compras na WEB' //vn_mensagem // Monta dados da conta corrente oCBX:CodigoAgencia := "0901.05" oCBX:NumeroContaCorrente := "0002105-3" oCBX:CodigoCedente := "02105" nSequenciaNossoNumero := 300000 + n && n ‚ do FOR nSequenciaNossoNumero := STR( nSequenciaNossoNumero, 6 ) oCBX:OutroDadoConfiguracao1 := Left(nSequenciaNossoNumero,1) //-- Prefixo do Nosso Numero q varia de 2 a 9 (Sicredi) && Comecei com 3 pq o Programa do Sicredi... &&.. come‡a com 2 oCBX:OutroDadoConfiguracao2 := "3" //-- Tipo de Cobran‡a 1 = com Registro 3 Sem registro (Sicredi) oCBX:InicioNossoNumero := Right( nSequenciaNossoNumero, 5) //"00001" oCBX:FimNossoNumero := "99999" oCBX:ProximoNossoNumero := strzero(n+1,5) // "00002" oBoleto := oCBX:DocumentosCobranca:Add() // Para fazer o X mai£sculo MDados := oBoleto:MeusDados:Add() MDados:Nome := "NumeroBancoXMaiusculo" MDados:Valor := "X" // Monta dados do sacado oBoleto:NomeSacado := "Nome do Sacado TESTE" oBoleto:CPFSacado := '93115610115' oBoleto:EnderecoSacado := 'Rua Teste, 1023' oBoleto:BairroSacado := 'CENTRO' oBoleto:CidadeSacado := 'CIDADE' oBoleto:EstadoSacado := 'MS' oBoleto:CepSacado := '89823460' // Monta dados do documento de cobrança oBoleto:DataDocumento := TRANSF( Date() - 1 ,'@E 99/99/9999' ) //"02/05/2012" oBoleto:DataProcessamento := TRANSF( Date() ,'@E 99/99/9999' ) //"03/05/2012" oBoleto:DataVencimento := TRANSF( Date() + (15*n),'@E 99/99/9999' ) //"21/05/2012" oBoleto:NumeroDocumento := 'TESTE.'+ STRZERO(n,3) //"12345" oBoleto:ValorDocumento := n * 8 oBoleto:ValorDesconto := {'0','1'}[n%2+1] // se for par pega o ZERO se for Impar pega o 1 oBoleto:ValorjurosdiaAtraso := 0 //{'0','2'}[n%2+1] // se for par pega o ZERO se for Impar pega o 1 oBoleto:TipoDocumentoCobranca :='DI' oCBX:ImprimeBoletos() oCBX := NIL NEXT RETURN( NIL ) Espero q ajude. Abraço
  13. e a UNINFS ou algo do tipo, teve um colega q comentou, alguém sabe algo a respeito?
  14. Se vc pesquisar no Youtube, instalar ACBr, vc terá video audas de como fazer, eu não achei o vídeo q fiz na época, eu instalei aki o Lazarus (Open source) ao invés do Delphie e baixa o projeto do ACBr via SVN... nesse vídeo mostra como fazer em Delphi mas a ideia é a mesma só q no Lazarus optei. Qdo vc baixa o Projeto tem uma pasta chamada Exemplos, ACBrDFe, ACBrNFSe Ai vc executa o Demo, q é totalmente funcional, preenche os dados da empresa emitente (isso pode ser salvo em um INI q é lido pelo ACBrNFSe Demo), com tb os dados do Certificado (nr de serie e senha) pasta dos Schemas (vem no projeto tb), pasta da logo, se vai salvar a NFSe emitida, aonda vai salvar, etc etc, Email e por ai vai, tipo ta tudo no jeito é só fazer ao invés de apertar o Gerar RPS, fazer monitorar uma pasta, veio o Arquivo tal, lá tem o comando por exemplo NFSe.GerarRPS ai carrega os serviços e informações necessárias e gera. (nessa parte q começamos a verificar) mas tem q dar certo, não tem segredo. Imagem sem título.tif
  15. Seguinte, to com um projeto em paralelo, o pessoal do ACBr tem isso funcionando pra vários e vários municipios, porém não liberaram no ACBrMonitorPlus, parece q quem criou isso no ACBr não quer q compartilhe com a comunidade, pq eu digo isso pq já tem um demo pronto q vc preenche as propriedades e pronto tudo funcionando, ou seja, pros caras incoporarem no ACBr é melzinho na chupeta, mas enfim, não vamos perder tempo. Contratei um rapaz q programa em Delphi pra fazer o Demo monitorar uma pasta, ai geramos um arquivo TEXTO/INI nessa pasta e ele vai ler e processar os comandos e devolver os retornos, ele começou esta semana, vamos ver se da conta, não programo em Delphi, mas olhando de fora como já tem o negócio pronto e lendo INI só falta fazer monitorar a pasta e devolver os retornos em arquivo TEXTO para tratarmos. Se tudo correr bem volto a postar aki. Ou seja, se vc tiver conhecimento ou alguém q entenda um pouco de Delphi pega esse demo q ta no projeto do ACBr e põe pra rodar ai.
  16. Uns 3 anos atrás pesquisei sobre o assunto e desenvolvi algum com uma classe na época mas q deixou de funcionar com a API do WhatsApp, abandonei o projeto, no forum FIVETECH tem o material a respeito, porém não fui mais atrás, não sei se nesse tempo alguém fez algo pra tal necessidade. Seria muito interessante, hj tenho a funcionalidade de envio de SMS etc, mas percebo q não é tão atrativo e útil qto ao envio via WhatsApp. Tb tenho interesse. Vou pesquisar e se encontrar algo posto aki. []´s Abaixo código feito em 2013 sobre o assunto usando a Classe q não é de minha autoria, e acabei não anotando onde consegui (desculpe autor) #include "hbsocket.ch" CLASS HB_WhatsApp DATA cAccount_status, cAccount_kind, cAccount_creation, cAccount_expiration DATA cNumber, cPassword, cNickname DATA pSocket DATA cServer INIT "s.whatsapp.net" DATA cHost INIT "bin-short.whatsapp.net" DATA cRealm INIT "s.whatsapp.net" DATA nPort INIT 5222 DATA cIP DATA cQop INIT "auth" DATA cDigest_Uri INIT "xmpp/s.whatsapp.net" DATA aResArray DATA cMsg DATA _Incomplete_message DATA LastSeen METHOD New( cNumber, cPassword, cNickname ) METHOD Connect() METHOD Login() METHOD Message( cMmsgid, cTo, cTxt ) METHOD Read() METHOD Send( cData ) METHOD parse_last_seen( cMsg ) METHOD parse_received_message( cMsg ) METHOD RequestLastSeen( mobile ) METHOD _Authenticate( cNonce, cNC ) METHOD _Identify( cStr ) METHOD _Is_Full_Msg( cStr ) METHOD parse_account_info( msg ) DESTRUCTOR Destroy() ENDCLASS METHOD New( cNumber, cPassword, cNickname ) CLASS HB_WhatsApp ::cIP = hb_socketGetHosts( ::cHost )[ 1 ] ::pSocket = hb_socketOpen() ::cNumber = cNumber ::cPassword = cPassword ::cNickname = cNickname return self METHOD Connect() CLASS HB_WhatsApp return hb_socketConnect( ::pSocket, { HB_SOCKET_AF_INET, ::cIP, ::nPort } ) function StrToHex( cStr ) local n, cHex := "" for n = 1 to Len( cStr ) cHex += "0x" + PadL( hb_NumToHex( Asc( SubStr( cStr, n, 1 ) ) ), "0", 2 ) if n < Len( cStr ) cHex += ", " endif next return cHex function random_uuid() return hb_strformat( "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",; hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ),; hb_Random( 0, 0xffff ),; hb_BitOr( hb_Random( 0, 0x0fff ), 0x4000 ),; hb_BitOr( hb_Random( 0, 0x3fff ), 0x8000 ),; hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ) ) METHOD Login() CLASS HB_WhatsApp local cBuffer, cResponse, aArrResponse, hAuthData, cValue, aResData, cResData ::Send( "WA" + Chr( 0x01 ) + Chr( 0x01 ) + Chr( 0 ) + ; Chr( 0x19 ) + Chr( 0xF8 ) + Chr( 0x05 ) + Chr( 0x01 ) + ; Chr( 0xA0 ) + Chr( 0x8A ) + Chr( 0x84 ) + Chr( 0xFC ) + ; Chr( 0x11 ) + "iPhone-2.6.9-5222" + ; Chr( 0 ) + Chr( 0x08 ) + Chr( 0xF8 ) + Chr( 0x02 ) + ; Chr( 0x96 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + ; Chr( 0x01 ) + Chr( 0x7E ) + Chr( 0 ) + Chr( 0x07 ) + Chr( 0xF8 ) + ; Chr( 0x05 ) + Chr( 0x0F ) + Chr( 0x5A ) + Chr( 0x2A ) + ; Chr( 0xBD ) + Chr( 0xA7 ) ) cBuffer = ::Read() cResponse = hb_base64decode( SubStr( cBuffer, 27 ) ) aArrResponse = HB_ATokens( cResponse, "," ) hAuthData = {=>} for each cValue in aArrResponse aResData = hb_ATokens( cValue, "=" ) hAuthData[ aResData[ 1 ] ] = StrTran( aResData[ 2 ], '"', "" ) next cResData = ::_Authenticate( hAuthData[ "nonce" ] ) cResponse = Chr( 0x01 ) + Chr( 0x31 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0x86 ) + ; Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0xFD ) + Chr( 0 ) + Chr( 1 ) + Chr( 0x28 ) + ; hb_base64encode( cResData ) ::Send( cResponse ) cBuffer = ::Read() ::Read() cResponse = Chr( 0 ) + Chr( 8 + Len( ::cNickname ) ) + Chr( 0xF8 ) + Chr( 5 ) + Chr( 0x74 ) + ; Chr( 0xA2 ) + Chr( 0xA3 ) + Chr( 0x61 ) + Chr( 0xFC ) + Chr( Len( ::cNickName ) ) + ; ::cNickName + Chr( 0 ) + Chr( 0x15 ) + Chr( 0xF8 ) + Chr( 6 ) + Chr( 0x48 ) + ; Chr( 0x43 ) + Chr( 5 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xF8 ) + Chr( 1 ) + ; Chr( 0xF8 ) + Chr( 4 ) + Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4D ) + Chr( 0xF8 ) + ; Chr( 1 ) + Chr( 0xF8 ) + Chr( 3 ) + Chr( 0x55 ) + Chr( 0x61 ) + Chr( 0x24 ) + ; Chr( 0 ) + Chr( 0x12 ) + Chr( 0xF8 ) + Chr( 8 ) + Chr( 0x48 ) + Chr( 0x43 ) + ; Chr( 0xFC ) + Chr( 1 ) + Chr( 0x32 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xA0 ) + ; Chr( 0x8A ) + Chr( 0xF8 ) + Chr( 1 ) + Chr( 0xF8 ) + Chr( 3 ) + Chr( 0x1F ) + ; Chr( 0xBD ) + Chr( 0xB1 ) ::Send( cResponse ) ::Read() return nil METHOD _Authenticate( cNonce, cNC ) CLASS HB_WhatsApp local cCNonce := random_uuid() local cA1 := hb_StrFormat( "%s:%s:%s", ::cNumber, ::cServer, ::cPassword ) local cA2, cPassword if cNC == nil cNC = "00000001" endif cA1 = pack_h32( hb_md5( cA1 ) ) + ":" + cNonce + ":" + cCNonce cA2 = "AUTHENTICATE:" + ::cDigest_Uri cPassword = hb_md5( cA1 ) + ":" + cNonce + ":" + cNC + ":" + cCNonce + ":" + ::cQop + ; ":" + hb_md5( cA2 ) cPassword = hb_md5( cPassword ) return hb_StrFormat( 'username="%s",realm="%s",nonce="%s",cnonce="%s",nc=%s,qop=%s,digest-uri="%s",response=%s,charset=utf-8',; ::cNumber, ::cRealm, cNonce, cCnonce, cNC, ::cQop, ::cDigest_Uri, cPassword ) METHOD Message( cMsgid, cTo, cTxt ) CLASS HB_WhatsApp local lLong_txt_bool := isShort( cTxt ) local cStream , cMsg, cContent, cTxt_length local cTo_length local cMsgid_length local cTotal_length cTo_length = Chr( Len( cTo ) ) cMsgid_length = Chr( Len( cMsgid ) ) cTxt_length = Chr( Len( cTxt ) ) cContent = Chr( 0xF8 ) + Chr( 0x08 ) + Chr( 0x5D ) + Chr( 0xA0 ) + Chr( 0xFA ) + Chr( 0xFC ) + cTo_length cContent += cTo cContent += Chr( 0x8A ) + Chr( 0xA2 ) + Chr( 0x1B ) + Chr( 0x43 ) + Chr( 0xFC ) + cMsgid_length cContent += cMsgid cContent += Chr( 0xF8 ) + Chr( 0x02 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0xBA ) + Chr( 0xBD ) + Chr( 0x4F) + ; Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0x8C ) + Chr( 0xF8 ) + Chr( 0x02 ) + Chr( 0x16 ) if ! lLong_txt_bool cContent += Chr( 0xFD ) + Chr( 0 ) + cTxt_length else cContent += Chr( 0xFC ) + cTxt_length endif cContent += cTxt cTotal_length = Chr( Len( cContent ) ) if Len( cTotal_length ) == 1 cTotal_length = Chr( 0 ) + cTotal_length endif cMsg := cTotal_length + cContent cStream := ::Send( cMsg ) ::Read() ::Read() ::Read() Return nil METHOD parse_received_message( cMsg ) CLASS HB_WhatsApp local message := { => }, nLength // RCVD MSG IN STRING nLength = Asc( SubStr( cMsg, 1, 1 ) ) message[ 'length' ] = nLength // PACKET EXCLUDING 00 AND FIRST HEX SHOULD EQUAL THIS NUMBER cMsg = SubStr( cMsg, 3 ) // Remove Length & F8 message[ 'sec_length' ] = Asc( SubStr( cMsg, 1, 1 ) ) // Length of something i dont know excatly what cMsg = SubStr( cMsg, 6 ) // Remove Second Length ( 1 HEX ) , Remove XML Chrs ( 4 HEX ) message[ 'from_number_length' ] = Asc( SubStr( cMsg, 1, 1 ) ) cMsg = SubStr( cMsg, 2 ) // Remove Length message[ 'from_number' ] = SubStr( cMsg, 1, message[ 'from_number_length' ] ) cMsg = SubStr( cMsg, message[ 'from_number_length' ] + 1 ) // Remove NUMBER cMsg = SubStr( cMsg,4 ) // Remove F8 & XML ( 2 HEX ) message[ 'message_id_length' ] = Asc( SubStr( cMsg, 1, 1 ) ) cMsg = Substr( cMsg, 2 ) // Remove Length message[ 'message_id' ] = SubStr( cMsg, 1, message[ 'message_id_length' ] ) cMsg = SubStr( cMsg, message[ 'message_id_length' ] + 1 ) cMsg = SubStr( cMsg, 5 ) // Remove XML ( 4 HEX ) message[ 'timestamp_length' ] = Asc( SubStr( cMsg, 1, 1 ) ) cMsg = SubStr( cMsg, 2 ) // Remove Length message[ 'timestamp' ] = Num2TS( Val( SubStr( cMsg, 1, message[ 'timestamp_length' ] ) ) ) cmsg = SubStr( cMsg, message[ 'timestamp_length' ] + 1 ) // Remove Timestamp // Check for Retry header if Substr( cMsg, 1, 1 ) == Chr( 0x88 ) cMsg = SubStr( cMsg, 5 ) // Remove Retry Length , i dont think i will need it endif cmsg = Substr( cMsg, 10 ) // Remove XMPP XML and Name XML Headers message[ 'sender_name_length' ] = Asc( SubStr( cMsg, 1, 1 ) ) cmsg = SubStr( cMsg, 2 ) // Remove Length message[ 'sender_name' ] = SubStr( cMsg, 1, message[ 'sender_name_length' ] ) cMsg = SubStr( cMsg, message[ 'sender_name_length' ] + 1 ) // Remove sender from msg cMsg = SubStr( cMsg, 10 ) // Remove body headers message[ 'body_txt_length' ] = Asc( SubStr( cMsg, 1, 1 ) ) cMsg = SubStr( cMsg, 2 ) // Remove Length message[ 'body_txt' ] = SubStr( cMsg, 1, message[ 'body_txt_length' ] ) cMsg = SubStr( cMsg, message[ 'body_txt_length' ] + 1 ) // Remove body txt cMsg = SubStr( cMsg, 10 ) // Remove XMPP XML and Name XML Headers message[ 'time_length' ] = Asc( SubStr( cMsg, 1, 1 ) ) cMsg = SubStr( cMsg, 2 ) // Remove Length message[ 'time' ] = SubStr( cMsg, 1, message[ 'time_length' ] ) cMsg = SubStr( cMsg, message[ 'time_length' ] + 1 ) // ? "From: " + message[ 'sender_name' ] + CRLF + ; // "msg: " + message[ 'body_txt' ] + CRLF + ; // "date: " + message[ 'timestamp' ] return message METHOD Read() CLASS HB_WhatsApp local cBuffer := Space( 1024 ), cV, cRcvdType local nLen := hb_socketRecv( ::pSocket, @cBuffer ) cBuffer = SubStr( cBuffer, 1, nLen ) ::aResArray = HB_ATokens( cBuffer, Chr( 0 ) ) // ? StrToHex( cBuffer ) for each cV in ::aResArray cRcvdType = ::_Identify( cV ) // ? cRcvdType // ? StrToHex( cV ) do case case cRcvdType == "incomplete_msg" ::_incomplete_message = cV case cRcvdType == "msg" ::cMsg = ::parse_received_message( cV ) case cRcvdType == "account_info" ::parse_account_info( cV ) case cRcvdType == "last_seen" ::lastseen = ::parse_last_seen( cV ) endcase next return cBuffer METHOD parse_account_info( cMsg ) local nAcst, nActkind local x := { => } local nCreation_timstamp_len, nExpr_length cMsg = SubStr( cMsg, 4 ) // Remove Length,F8,second length cMsg = SubStr( cMsg, 5 ) // Remove Success XML // Next should be status nAcst = Asc( SubStr( cMsg, 1, 1 ) ) if nAcst == 0x09 ::cAccount_status = 'active' else ::cAccount_status = 'inactive' endif cMsg = SubStr( cMsg, 3 ) // Remove status & KIND XML nActkind = Asc( SubStr( cMsg, 1, 1 ) ) if nActkind == 0x37 ::cAccount_kind = 'free' else ::cAccount_kind = 'paid' endif cMsg = SubStr( cMsg, 4 ) // Remove XML nCreation_timstamp_len = Asc( SubStr( cMsg, 1, 1 ) ) // Should return 10 for the next few thousdands years cMsg = SubStr( cMsg, 2 ) // Remove Length ::cAccount_creation := Num2TS( Val( SubStr( cMsg, 1, nCreation_timstamp_len ) ) ) cMsg = SubStr( cMsg, nCreation_timstamp_len + 1 ) // Remove Timestamp cMsg = SubStr( cMsg, 3 ) // Remove Expiration XML nExpr_length = Asc( SubStr( cMsg, 1, 1 ) ) // Should also be 10 cMsg = SubStr( cMsg, 2 ) // Remove Length ::cAccount_expiration := Num2TS( Val( SubStr( cMsg, 1, nExpr_length ) ) ) return nil METHOD RequestLastSeen( mobile ) CLASS HB_WhatsApp local mob_len, content, len, total_length, request, stream mob_len = Chr( Len( mobile ) ) content = Chr( 0xF8 ) + Chr( 0x08 ) + Chr( 0x48 ) + Chr( 0x43 ) + Chr( 0xFC ) content += Chr( 0x01 ) + Chr( 0x37 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xA0 ) content += Chr( 0xFA ) + Chr( 0xFC ) + mob_len content += mobile content += Chr( 0x8A ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + Chr( 0x03 ) content += Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4C ) len = Len( content ) total_length = Chr( len ) request = Chr( 0 ) request += total_length request += content stream = ::Send( request ) ::Read() ::Read() return nil METHOD parse_last_seen( cMsg ) CLASS HB_WhatsApp Local lastseen := {=>}, moblen, last_seen_len cMsg = SubStr( cMsg, 8 ) // Remove Some XML DATA moblen= Asc( SubStr( cMsg, 1, 1 ) ) cMsg = SubStr( cMsg, 2 ) // Remove Length lastseen[ 'mobile' ] = SubStr( cMsg, 1, moblen ) cMsg = SubStr( cMsg, moblen + 1 ) cMsg = SubStr( cMsg, 17 ) // Remove Some More XML DATA last_seen_len = Asc( SubStr( cMsg, 1, 1 ) ) cmsg = SubStr( cMsg, 2 ) // Remove Length lastseen[ 'seconds_ago' ] = SubStr( cMsg, 0, last_seen_len ) return lastseen METHOD Send( cData ) CLASS HB_WhatsApp return hb_socketSend( ::pSocket, cData ) function StartsWith( cStr, cCompare, nPos ) return SubStr( cStr, nPos, Len( cCompare ) ) == cCompare function EndsWith( cStr, cCompare ) return Right( cStr, Len( cCompare ) ) == cCompare METHOD _Identify( cStr ) CLASS HB_WhatsApp local cMsg_identifier := Chr( 0x5D ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC ) local cServer_delivery_identifier := Chr( 0x8C ) local cClient_delivery_identifier := Chr( 0x7F ) + Chr( 0xBD ) + Chr( 0xAD ) local cAcc_info_iden := Chr( 0x99 ) + Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0x94 ) local cLast_seen_ident := Chr( 0x48 ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC ) local cLast_seen_ident2 := Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4C ) + Chr( 0x8B ) if ! ::_is_full_msg( cStr ) return "incomplete_msg" elseif StartsWith( cStr, cMsg_identifier, 4 ) if EndsWith( cStr, cServer_delivery_identifier ) return "server_delivery_report" elseif EndsWith( cStr, cClient_delivery_identifier ) return "client_delivery_report" else return "msg" endif elseif StartsWith( cStr, cAcc_info_iden, 4 ) return "account_info" elseif StartsWith( cStr, cLast_seen_ident, 4 ) .and. cLast_seen_ident2 $ cStr return "last_seen" else return "other" endif return nil METHOD _Is_Full_Msg( cStr ) CLASS HB_WhatsApp return Len( cStr ) == Asc( Left( cStr, 1 ) ) + 1 METHOD Destroy() CLASS HB_WhatsApp HB_SocketShutDown( ::pSocket ) HB_SocketClose( ::pSocket ) ::pSocket = nil return nil function pack_h32( cString ) local c := "", cLeter local nibbleshift := 4 local n local nPos := 0 local aOut := {} for each cLeter in cString n = asc( cLeter ) if n >= asc( "0" ) .and. n <= asc( "9" ) n -= asc( "0" ) elseif n >= asc( "a" ) .and. n <= asc( "f" ) n -= ( asc( "a" ) - 10 ) elseif n >= asc( "F" ) .and. n <= asc( "F" ) n -= ( asc( "A" ) - 10 ) endif if cLeter:__enumindex() % 2 != 0 AAdd( aOut, 0 ) nPos++ endif aOut[ nPos ] = hb_BitOr( aOut[ nPos ], hb_BitShift( n, nibbleshift ) ) nibbleshift = hb_BitAnd( ( nibbleshift + 4 ), 7 ) if cLeter:__enumindex() % 2 == 0 c += Chr( aOut[ nPos ] ) endif next return c static function Num2Days( timet ) return (timet) / (24.0 * 60.0 * 60.0) static function Num2TS( n ) local fecha, hour, min, sec, time, datetime local t2d := Num2Days( n ) fecha = Num2Date( n ) hour = ( t2d - int( t2d ) ) * 24 min = ( hour - int( hour ) ) * 60 sec = ( min - int( min ) ) * 60 time = strzero( int( hour ), 2 ) + strzero( int( min ), 2 ) + strzero( int( sec ), 2 ) datetime = dtos( fecha ) + time return hb_tstostr( hb_stot( datetime ) ) function Num2Date( n ) local fecha local t2d := Num2Days( n ) fecha := SToD( "19700101" ) + int( t2d ) return fecha function TS2Num( dt ) local fecha local nNum DEFAULT dt TO hb_DateTime() nNum = ( hb_Hour( dt ) * 24 + hb_Minute( dt ) * 60 + hb_sec( dt ) * 60 ) / 86400 nNum += ( hb_TToD( dt ) - SToD( "19700101" ) ) nNum *= 86400 nNum = Int( nNum ) return nNum static function isShort( str ) return Len( str ) < 256 #pragma BEGINDUMP #include <hbapi.h> HB_FUNC( STRREV ) { int iLen = hb_parclen( 1 ), i; char * buffer = ( char * ) hb_xgrab( iLen ); for( i = 0; i < iLen; i++ ) buffer[ i ] = hb_parc( 1 )[ iLen - i - 1 ]; hb_retclen( buffer, iLen ); hb_xfree( buffer ); } #pragma ENDDUMP Pra usar (não lembro exatamente, vou postar o código apenas): METHOD Button1Click( oSender ) CLASS frmMain LOCAL cPhone := AllTrim(::oSourcePhone:cText) // Your Phone LOCAL lIphone := IF( ::oDevice:nIndex == 1, .T., .F.) // .T. IPhone .F. Android LOCAL cImei := ::oPass:cText // WIFI MAC (IPhone) IMEI (Android) LOCAL cNickName := ::oNick:cText LOCAL cTelefono := AllTrim(::oDestPhone:cText) // Destination Phone LOCAL cMensaje := ::oMessage:cText LOCAL oWA // cImei 0C:74:C2:99:2A:65' / '357956040139430' // mac de wifi paraiphone , Imei para Android DEFAULT cPhone TO '5511970707070' // Your Phone DEFAULT lIphone TO .T. // .T. IPhone .F. Android DEFAULT cImei TO IF(lIphone, '0D:74:D2:99:2B:65', '157956050132421') DEFAULT cNickName TO 'Teste' DEFAULT cTelefono TO '5511970508070' DEFAULT cMensaje TO 'Testando' // oWA := HB_WhatsApp():New( "CountryAndYourAndroidPhoneNumber", hb_md5( StrRev( "AndroidIMEI" ) ), "YourNickname" ) oWA := HB_WhatsApp():New( cPhone, hb_md5( IF( !lIphone, StrRev( cImei ), cImei+cImei ) ),cNickName ) LogDebug( oWA:Connect() ) oWA:Login() LogDebug( oWA:cAccount_status, oWA:cAccount_kind, oWA:cAccount_creation, oWA:cAccount_expiration ) LogDebug( oWA:RequestLastSeen( cTelefono ) ) LogDebug( oWA:LastSeen[ 'seconds_ago' ] ) oWA:Message( Str( TS2Num() ), AllTrim(cTelefono), AllTrim(cMensaje) ) RETURN Nil //------------------------------------------------------------------------------ METHOD PassEnter( oSender, oPrevCtl ) CLASS frmMain IF ::oDevice:nIndex == 1 oSender:cPicture := 'XX:XX:XX:XX:XX:XX' //0C:74:C2:99:2A:65 ELSE oSender:cPicture := '999999999999999' // '357956040139430' ENDIF RETURN Nil
  17. Se entendi o q esses programas fazem é escanear e transformar em JPG ou PDF depois processar essas imagens via OCR ou outra tecnologia e ai é trabalhar o resultado, localizando a informação relativa a etiqueta e salvando. Não tenho nada pronto nesse sentido, seria apenas hipóteses de possíveis formas de se fazer isso. Dentro deste raciocínio seguem alguns links q achei sobre a questão de converter / ler o conteúdo do q é escaneado, mas tem mais. http://fivetechsupport.com/forums/viewtopic.php?f=6&t=11233 http://fivetechsupport.com/forums/viewtopic.php?f=3&t=24030&start=0
  18. Thotokos, mas se o usuário copiar e colar vai o caracter especial junto
  19. pra não fugir ao tópico poderia apenas indicar um link sobre como não usar DBF nem pra temporário?
  20. Obrigado, com certeza será útil a muitos.
  21. Desculpe a lógica pq qdo fiz na época foi as pressas (kkkk como se nossas demandas não fossem pra ontem...) Espero q ajude, no caso a importação abaixo fiz conforme a necessidade aki, talvez tenha campos q vc precise q não estejam ou alguns q não precise, ai tem q rever o Layout do arquivo q no momento não achei, tem q dar uma procurada na net, mas lembro q acha fácil. /* * Projeto..: ERP * Arquivo..: Aux_Fiscal.prg * Descrição: Importa Mapa Resumo baseado no ATO_TDM_DATA // Modo CONSOLE * Autor....: Fladimir * Data.....: 21-10-2013 */ function ImportaMapaResdoAtoTDM() LOCAL getlist:= {}, nOpcAddouDel xCancelamentos := 0 ; xAcrescimos := 0 ; xDescontos := 0 xST := 0 ; xIS := 0 ; xNT := 0 xAliq1 := 0 ; xVlr_Aliq1 := 0 xAliq2 := 0 ; xVlr_Aliq2 := 0 xAliq3 := 0 ; xVlr_Aliq3 := 0 xAliq4 := 0 ; xVlr_Aliq4 := 0 xAliq5 := 0 ; xVlr_Aliq5 := 0 xAliq6 := 0 ; xVlr_Aliq6 := 0 xAliq7 := 0 ; xVlr_Aliq7 := 0 xAliq8 := 0 ; xVlr_Aliq8 := 0 xAliq9 := 0 ; xVlr_Aliq9 := 0 xAliquota := 0 CLS ALERT('É necessario o arquivo ATO_TDM_DATA.TXT na pasta',{'Ok'}) SET(_SET_DATEFORMAT,"DD/MM/YYYY") SET DATE TO BRITISH // Preciso do Arquivo texto com o nome de: cArqTXT := 'ATO_TDM_DATA.TXT' + SPACE(10) nGTBase := 0 @ 10,05 say 'Arquivo..........................:' get cArqTXT @ 11,05 say 'GT ap¢s ultimo periodo do arquivo:' GET nGTBase PICT '@E 999,999,999.999' READ cArqTXT := ALLTRIM(cArqTXT) cArqPonte := 'Ponte.dbf' FErase(cArqPonte) aStru := { {"Linha" ,'C', 255,0} } DBCREATE(cArqPonte,aStru) Use Ponte ALIAS Ponte shared new APPEND FROM &cArqTXT SDF USE MAPARES ALIAS MAPARES EXCLUSIVE NEW ZAP Ponte->(dbgotop()) While Ponte->(!EOF()) if LEFT(Ponte->Linha,3) == 'E01' .OR.; LEFT(Ponte->Linha,3) == 'E02' .OR.; LEFT(Ponte->Linha,3) == 'E03' .OR.; LEFT(Ponte->Linha,3) == 'E04' .OR.; LEFT(Ponte->Linha,3) == 'E05' .OR.; LEFT(Ponte->Linha,3) == 'E06' .OR.; LEFT(Ponte->Linha,3) == 'E07' .OR.; LEFT(Ponte->Linha,3) == 'E08' .OR.; LEFT(Ponte->Linha,3) == 'E09' .OR.; LEFT(Ponte->Linha,3) == 'E10' Ponte->(dbskip()) LOOP endif if LEFT(Ponte->Linha,3) == 'E11' nGTFin := SUBSTR(Ponte->Linha, 105, 18) nGTFin := Val( nGTFin ) / 100 lE11 := .T. endif if ! lE11 // Se nao tem E11 sinal q o arquivo de origem esta incorreto com o layout Alert('Falha no arquivo processo interrompido') QUIT endif Ponte->(dbskip()) // vai pro(s) E12 While LEFT(Ponte->Linha,3) == 'E12' xNumECF := SUBSTR(Ponte->Linha, 45, 02 ) //-- Campo 05 = Nr Ordem ECF xSerie := SUBSTR(Ponte->Linha, 04, 20 ) //-- Campo 02 = Nr Serie ECF xDataMovZ := SUBSTR(Ponte->Linha, 65, 08 ) //-- Campo 09 20140115 xDataMovZ := RIGHT(xDataMovZ,2) + '/' + SUBSTR(xDataMovZ, 5,2) + '/' + LEFT(xDataMovZ,4) xCRO := SUBSTR(Ponte->Linha, 59, 06 ) //-- Campo 08 CRZ_E12 := SUBSTR(Ponte->Linha, 47, 06 ) //-- Campo 06 xCOO_FIM := SUBSTR(Ponte->Linha, 53, 06 ) //-- Campo 07 xVendaBruta := SUBSTR(Ponte->Linha, 87, 14 ) //-- Campo 12 xVendaBruta := VAL( xVendaBruta) / 100 nRecE12 := Ponte->(recno()) // pra saber qual linha estava no E12 pois as E12 sao seguidas entÆo se 5 reducoes 5 E12 //-- Vai para o proximo E13 While .T. Ponte->(dbskip()) if LEFT(Ponte->Linha,3) == 'E12' // Se ainda é E12 vai pra proxima else EXIT endif end // Tenho q pegar o CRZ do E12 e avaliar se tem E13 com mesma reducao ai processo. xAliq1 := 0 ; xVlr_Aliq1 := 0 xAliq2 := 0 ; xVlr_Aliq2 := 0 xAliq3 := 0 ; xVlr_Aliq3 := 0 xAliq4 := 0 ; xVlr_Aliq4 := 0 xAliq5 := 0 ; xVlr_Aliq5 := 0 xAliq6 := 0 ; xVlr_Aliq6 := 0 xAliq7 := 0 ; xVlr_Aliq7 := 0 xAliq8 := 0 ; xVlr_Aliq8 := 0 xAliq9 := 0 ; xVlr_Aliq9 := 0 While .T. CRZ_E13 := SUBSTR(Ponte->Linha, 47, 6 ) // Define o q é Entao se Campo 7 for Can-T == Cancelament if LEFT(Ponte->Linha,3) == 'E13' .AND. CRZ_E12 == CRZ_E13 // To no E13 ainda se E12 terminou o E13 ai grava o q tiver xCampo7 := SUBSTR(Ponte->Linha, 53, 5 ) // Define o q é Entao se Campo 7 for Can-T == Cancelament xCampo8 := SUBSTR(Ponte->Linha, 60, 13 ) // Valor xCampo8 := VAL(xCampo8) / 100 //Campo 8 se Campo 7 == Fxx if left(xCampo7,3) == 'Can-T' ; xCancelamentos := xCampo8 ; endif if left(xCampo7,2) == 'DT' ; xDescontos := xCampo8 ; endif if left(xCampo7,2) == 'AT' ; xAcrescimos := xCampo8 ; endif if left(xCampo7,1) == 'I' ; xIS := xCampo8 ; endif if left(xCampo7,1) == 'F' ; xST := xCampo8 ; endif if left(xCampo7,1) == 'N' ; xNT := xCampo8 ; endif if VAL(LEFT(xCampo7,2)) > 0 // Tributadas '03T17' // Tributadas nIDAliq := VAL(LEFT(xCampo7,2)) // 03 xAliquota := VAL(ALLTRIM(SUBSTR(xCampo7, 4)) + '00')/100 // 17,00 if nIDAliq == 1 xAliq1 := xAliquota xVlr_Aliq1 := xCampo8 elseif nIDAliq == 2 xAliq2 := xAliquota xVlr_Aliq2 := xCampo8 elseif nIDAliq == 3 xAliq3 := xAliquota xVlr_Aliq3 := xCampo8 elseif nIDAliq == 4 xAliq4 := xAliquota xVlr_Aliq4 := xCampo8 elseif nIDAliq == 5 xAliq5 := xAliquota xVlr_Aliq5 := xCampo8 elseif nIDAliq == 6 xAliq6 := xAliquota xVlr_Aliq6 := xCampo8 elseif nIDAliq == 7 xAliq7 := xAliquota xVlr_Aliq7 := xCampo8 elseif nIDAliq == 8 xAliq8 := xAliquota xVlr_Aliq8 := xCampo8 elseif nIDAliq == 9 xAliq9 := xAliquota xVlr_Aliq9 := xCampo8 endif endif endif Ponte->(dbskip()) if Ponte->(EOF()) EXIT endif end // do E13 AuxImpMP() // Grava a Redu‡Æo Z Ponte->(dbgoto(nRecE12)) //Posiciona no Registro 12 ultimo Ponte->(DbSkip()) //Pula pra ver se tem outro 12 e repete o processo end //se nÆo tem outro 12 ‚ pq terminou os 12 ai termina EXIT end DbCloseAll() *-- Ajusta GTFinal Use mapares alias mapares shared new Ferase('_TempImpZ.CDX') index on MapaRes->datamovz to _TempImpZ DESCENDING Go Top nSaldo := nGTBase While !EOF() Mapares->(BlokRegistro()) MapaRes->GT_Final := nSaldo nSaldo := MapaRes->GT_Final - MapaRes->VendaBruta DbSkip() end DbCommitAll() MapaRes->(DBCLOSEAREA()) Alert('Rotina finalizada com sucesso', aOk) cls return //-- Para o MapaResumo #define D_NR_MAPARES 1 #define D_DATAMOVZ 2 #define D_HORA_Z 3 #define D_NUMECF 4 #define D_NUMSERIE 5 #define D_GNF 6 #define D_CRO 7 #define D_CRZ 8 #define D_CCF 9 #define D_CFD 10 #define D_CCDC 11 #define D_GRG 12 #define D_GNFC 13 #define D_CFC 14 #define D_COO_INI 15 #define D_COO_FIM 16 #define D_GT_INICIAL 17 #define D_GT_FINAL 18 #define D_VENDABRUTA 19 #define D_CANCELAMEN 20 #define D_DESCONTOS 21 #define D_ACRESCIMOS 22 #define D_ALIQUOTA1 23 #define D_VLR_ALIQ1 24 #define D_ALIQUOTA2 25 #define D_VLR_ALIQ2 26 #define D_ALIQUOTA3 27 #define D_VLR_ALIQ3 28 #define D_ALIQUOTA4 29 #define D_VLR_ALIQ4 30 #define D_ALIQUOTA5 31 #define D_VLR_ALIQ5 32 #define D_ALIQUOTA6 33 #define D_VLR_ALIQ6 34 #define D_ALIQUOTA7 35 #define D_VLR_ALIQ7 36 #define D_ALIQUOTA8 37 #define D_VLR_ALIQ8 38 #define D_ALIQUOTA9 39 #define D_VLR_ALIQ9 40 #define D_SUBST_TRIB 41 #define D_ISENTO 42 #define D_NAO_INCIDE 43 ******************************************************************************** function AuxImpMP LOCAL getlist :={}, aGet:={} aGet := InicializaVar('MAPARES', aGet) aGet := ZeraVariaveis('MAPARES', aGet) aGet[D_NR_MAPARES] := PegaNrMapaResumo() // sequencial MapaRes->( AdicionaReg() ) aGet[D_DATAMOVZ] := CTOD( xDataMovZ ) aGet[D_NUMSERIE] := xSerie aGet[D_NUMECF] := STRZERO(VAL(xNumECF),3) // Coloquei para for‡ar o formato 001 ao inv‚s de 1 aGet[D_COO_FIM] := VAL( xCOO_FIM ) //= 000119 aGet[D_CRZ] := VAL( CRZ_E12 ) //= 0008 aGet[D_CRO] := VAL( xCRO ) //= 0002 aGet[D_GT_FINAL] := nGTFin aGet[D_VENDABRUTA] := xVendaBruta aGet[D_DESCONTOS] := xDescontos aGet[D_CANCELAMEN] := xCancelamentos aGet[D_ACRESCIMOS] := xAcrescimos aGet[D_SUBST_TRIB] := xST aGet[D_NAO_INCIDE] := xNT aGet[D_ISENTO] := xIS aGet[D_ALIQUOTA1] := xAliq1 aGet[D_VLR_ALIQ1] := xVlr_Aliq1 aGet[D_ALIQUOTA2] := xAliq2 aGet[D_VLR_ALIQ2] := xVlr_Aliq2 aGet[D_ALIQUOTA3] := xAliq3 aGet[D_VLR_ALIQ3] := xVlr_Aliq3 aGet[D_ALIQUOTA4] := xAliq4 aGet[D_VLR_ALIQ4] := xVlr_Aliq4 aGet[D_ALIQUOTA5] := xAliq5 aGet[D_VLR_ALIQ5] := xVlr_Aliq5 aGet[D_ALIQUOTA6] := xAliq6 aGet[D_VLR_ALIQ6] := xVlr_Aliq6 aGet[D_ALIQUOTA7] := xAliq7 aGet[D_VLR_ALIQ7] := xVlr_Aliq7 aGet[D_ALIQUOTA8] := xAliq8 aGet[D_VLR_ALIQ8] := xVlr_Aliq8 aGet[D_ALIQUOTA9] := xAliq9 aGet[D_VLR_ALIQ9] := xVlr_Aliq9 MapaRes->( BlokRegistro() ) GravaVariaveis('MAPARES', aGet) return
×
×
  • Create New...